通信协议综述 为什么要学习网络协议? 1 2 要打造互联网世界的通天塔,只教给一台机器做什么是不够的,你需要学会教给一大片机器做什么。这就需要网络协议 通过网络协议,才能使一大片机器互相协作、共同完成一件事。
网络分层 1 2 3 为什么分层: 复杂的程序都分层,程序设计要求 层层封装: 只要是在网络上跑的包,都是完整的。可以有下层没上层,绝对不可能有上层没下层。
ifconfig 命令 1 2 3 4 5 6 7 8 linux 查看ip地址: ifconfig, ip addr (工具: net-tools 和 iproute2 的故事) 大部分的网卡都会有一个 IP 地址, 不是必需 IP 地址是一个网卡在网络世界的通讯地址, 相当于门牌号, 不可冲突 例: 10.100.122.2 就是一个 IP 地址。这个地址被点分隔为四个部分,每个部分 8 个 bit,所以 IP 地址总共是 32 位 因为不够用,于是就有了 IPv6,也就是上面输出结果里面 inet6 fe80::f816:3eff:fec7:7975/64。这个有 128 位
当初设计哪知道现在会有这么多计算机, 本来 32 位的 IP 地址就不够,还被分成了 5 类
1 2 3 4 5 对于 A、B、 C 类主要分两部分,前面一部分是网络号,后面一部分是主机号 问题: C 类地址能包含的最大主机数量实在太少了,只有 254 个 而 B 类地址能包含的最大主机数量又太多了, 一般企业达不到6万多台机器, 闲着浪费
1 2 3 4 5 6 7 8 9 10 将 32 位的 IP 地址一分为二,前面是网络号,后面是主机号 例: 10.100.122.2/24 这种地址表示形式,就是 CIDR。后面 24 的意思是,32 位中,前 24 位是网络号,后 8 位是主机号 伴随着 CIDR 存在的: 一个是广播地址,10.100.122.255。如果发送这个地址,所有 10.100.122 网络里面的机器都可以收到 另一个是子网掩码,255.255.255.0 将子网掩码和 IP 地址按位计算 AND,就可得到网络号: 如上面例子网络号就是: 10.100.122.0
1 2 3 4 5 6 7 日常工作现在都是 CIDR, 几乎不用划分 A 类、B 类或者 C 类. 私有IP: 是一个组织内部的, 公网之间可以重复 公有IP: 是分配的的,需要买 在ABC类IP地址中, 私有IP在上图中 CIDR中常见的是 /24 的私有IP, 如: 192.168.0.x , 一般私有网络的出口地址,像路由器是 192.168.0.1, 而192.168.0.255是广播地址
ip addr 的继续分析 1 2 3 4 5 6 7 8 9 10 11 12 13 root@test:~# ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether fa:16:3e:c7:79:75 brd ff:ff:ff:ff:ff:ff inet 10.100.122.2/24 brd 10.100.122.255 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::f816:3eff:fec7:7975/64 scope link valid_lft forever preferred_lft forever
1 2 3 4 5 6 在 IP 地址的后面有个 scope 对于 eth0 这张网卡来讲,是 global,说明这张网卡是可以对外的,可以接收来自各个地方的包。 对于 lo 来讲,是 host,说明这张网卡仅仅可以供本机相互通信。 lo 全称是 loopback,又称环回接口,往往会被分配到 127.0.0.1 这个地址。 这个地址用于本机通信,经过内核处理后直接返回,不会在任何网络中出现。
在 IP 地址的上一行是 link/ether fa:16:3e:c7:79:75 brd ff:ff:ff:ff:ff:ff,这个被称为 MAC 地址,是一个网卡的物理地址,用十六进制,6 个 byte 表示
1 2 3 4 5 6 7 8 9 10 号称 全局唯一, 不会有两个网卡有相同的 MAC 地址,而且网卡自生产出来,就带着这个地址 误解:MAC地址唯一,那整个互联网的通信,全部用 MAC 地址好了,只要知道了对方的 MAC 地址,就可以把信息传过去。 正解: 一个网络包要从一个地方传到另一个地方,除了要有确定的地址,还需要有定位功能。 而有门牌号码属性的 IP 地址,才是有远程定位功能的 MAC 地址更像是身份证,是一个唯一的标识 MAC 地址是有一定定位功能的,只不过范围非常有限, 局限在一个子网里面。 例: 从 192.168.0.2/24 访问 192.168.0.3/24 是可以用 MAC 地址的。
<BROADCAST,MULTICAST,UP,LOWER_UP> 是干什么的?这个叫做 net_device flags,网络设备的状态标识。
1 2 3 4 UP 表示网卡处于启动的状态; BROADCAST 表示这个网卡有广播地址,可以发送广播包; MULTICAST 表示网卡可以发送多播包; LOWER_UP 表示 L1 是启动的,也即网线插着呢。
MTU1500 是指什么意思呢?是哪一层的概念呢?最大传输单元 MTU 为 1500,这是以太网的默认值。
1 2 3 MTU 是二层 MAC 层的概念。 MAC 层有 MAC 的头,以太网规定正文部分不允许超过 1500 个字节。 正文里面有 IP 的头、TCP 的头、HTTP 的头。如果放不下,就需要分片来传输。
qdisc pfifo_fast 是什么意思呢?qdisc 全称是 queueing discipline,中文叫排队规则。
1 2 3 4 5 6 7 8 内核如果需要通过某个网络接口发送数据包,它都需要按照为这个接口配置的 qdisc(排队规则)把数据包加入队列 队列类型: pfifo : 最简单, 先进先出 pfifo_fast : 它的队列包括三个波段(band)。在每个波段里面,使用先进先出规则。 三个波段(band)的优先级也不相同。band 0 最高,band 2 最低。 如果 band 0 里面有数据包,系统就不会处理 band 1 里面的数据包 数据包是按照服务类型(Type of Service,TOS)被分配到三个波段(band)里面的。TOS 是 IP 头里面的一个字段,代表了当前的包是高优先级的,还是低优先级的
总结
IP 是地址,有定位功能;MAC 是身份证,无定位功能;
CIDR 可以用来判断是不是本地人;
IP 分公有的 IP 和私有的 IP
DHCP 和 PXE : IP怎么来? 怎么没? 如何配置IP地址 使用 net-tools
1 2 $ sudo ifconfig eth1 10.0.0.1/24 $ sudo ifconfig eth1 up
使用 iproute2:
1 2 $ sudo ip addr add 10.0.0.1/24 dev eth1 $ sudo ip link set up eth1
思考: 192.168.1.6 就在你这台机器的旁边,甚至是在同一个交换机上,而你把机器的地址设为了 16.158.23.6。 为什么ping不通?
1 2 3 4 5 6 7 8 9 原则: 只要是在网络上跑的包,都是完整的,可以有下层没上层,绝对不可能有上层没下层。 逻辑分析: 它有自己的源 IP 地址 16.158.23.6,也有目标 IP 地址 192.168.1.6,但是包发不出去,这是因为 MAC 层还没填 Linux 首先会判断,要去的这个地址和我是一个网段的吗,或者和我的一个网卡是同一网段的吗? 只有是一个网段的,它才会发送 ARP 请求,获取 MAC 地址 如果不是, 这是一个跨网段的调用,它便不会直接将包发送到网络上,而是企图将包发送到网关。 而linux中网关的配置, 网关要和当前的网络至少一个网卡是同一个网段的
1 不同系统的配置文件格式不同,但是无非就是 CIDR、子网掩码、广播地址和网关地址。
动态主机配置协议(DHCP)(Dynamic Host Configuration Protocol) 1 2 3 他只需要配置一段共享的 IP 地址。 每一台新接入的机器都通过 DHCP 协议,来这个共享的 IP 地址里申请,然后自动配置好就可以了。 等人走了,或者用完了,还回去,这样其他的机器也能用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 第一步. client进行 DHCP Discover ( 广播 Boot request,我的 MAC 地址是这个,我还没有 IP) 新机器使用 IP 地址 0.0.0.0 发送了一个广播包,目的 IP 地址为 255.255.255.255。广播包封装了 UDP,UDP 封装了 BOOTP。 (其实 DHCP 是 BOOTP 的增强版) 第二步. DHCP server 进行 DHCP offer MAC地址唯一,新MAC地址来了,分配IP地址,并为他保留 。 仍然使用广播地址作为目的地址 第三步,client 进行 DHCP request 新机器得到 offer, 如果有多个DHCP server, 甚至得到多个offer 一般选择最新到达的offer,然后向网络发送一个 DHCP Request 广播数据包,包中包含客户端的 MAC 地址、接受的租约中的 IP 地址、提供此租约的 DHCP 服务器地址等 告诉所有 DHCP Server 它将接受哪一台服务器提供的 IP 地址,告诉其他 DHCP 服务器,谢谢你们的接纳,并请求撤销它们提供的 IP 地址,以便提供给下一个 IP 租用请求者 由于还没有得到 DHCP Server 的最后确认,客户端仍然使用 0.0.0.0 为源 IP 地址、255.255.255.255 为目标地址进行广播 第四步, server 进行 DHCP ACK 当 DHCP Server 接收到客户机的 DHCP request 之后, 会广播返回给客户机一个 DHCP ACK 消息包,表明已经接受客户机的选择,并将这一 IP 地址的合法租用信息和其他的配置信息都放入该广播包,发给客户机,欢迎它加入网络大家庭。 广播也是告诉其他server, 该client在我这个server租了IP
1 2 3 续租: 客户机会在租期过去 50% 的时候,直接向为其提供 IP 地址的 DHCP Server 发送 DHCP request 消息包 客户机接收到该服务器回应的 DHCP ACK 消息包,会根据包中所提供的新的租期以及其他已经更新的 TCP/IP 参数,更新自己的配置
自动安装操作系统
场景: 数据中心里面的管理员可能一下子就拿到几百台空的机器,一个个安装操作系统,会累死的
1 2 3 4 5 6 7 8 9 10 11 办法: 安装的操作系统放在一个服务器上,让客户端去下载。 问题: 没有操作系统,客户端放哪里? 解决: 操作系统的启动过程: 首先启动BIOS, 读取硬盘的 MBR 启动扇区,将 GRUB 启动起来;然后将权力交给 GRUB,GRUB 加载内核、加载作为根文件系统的 initramfs 文件;然后将权力交给内核;最后内核启动,初始化整个操作系统 在整个过程中, 只能放在BIOS启动后,因为没安装系统之前,连启动扇区都没有 这个过程叫做预启动执行环境(Pre-boot Execution Environment),简称 PXE。 PXE 协议分为客户端和服务器端,由于还没有操作系统,只能先把客户端放在 BIOS 里面。当计算机启动时,BIOS 把 PXE 客户端调入内存里面,就可以连接到服务端做一些操作了 首先 PXE 的客户端启动起来,发送一个 DHCP 的请求,让 DHCP Server 给它分配一个地址。PXE 客户端有了自己的地址 怎么知道 PXE 服务器在哪里呢? 在DHCP server 中配置 next-server,指向 PXE 服务器的地址,配置初始启动文件位置 filename 然后TFTP,从 PXE服务器下载
PXE 工作过程
底层网络知识详解: 从二层到三层 从 物理层 到 MAC层 : 学校宿舍几台电脑之间联网 物理层 1 2 3 4 5 6 7 8 9 使用路由器联网,是在第三层 物理层联网: 两台电脑: 在物理层联网, 一根网线连接两台电脑的网口 但普通的网线不行,水晶头要做交叉线,就是所谓的 1-3、2-6 交叉接法。 (水晶头的第 1、2 和第 3、6 脚,它们分别起着收、发信号的作用。将一端的 1 号和 3 号线、2 号和 6 号线互换一下位置,就能够在物理层实现一端发送的信号,另一端能收到) 然后配置两台电脑的 IP 地址、子网掩码和默认网关, 配置成同一个网络, 例:可以一个是 192.168.0.1/24,另一个是 192.168.0.2/24 三台电脑: 使用集线器Hub,和交换机不同,没有大脑,完全在物理层工作,将收到的字节复制到其他接口
数据链路层 (第二层)
问题: 多台电脑使用Hub进行物理层联网后: 广播,一台电脑发出的包所有电脑都能收到
这个包是发给谁的?谁应该接收?
大家都在发,会不会产生混乱?有没有谁先发、谁后发的规则?
如果发送的时候出现了错误,怎么办?
在第二层, 数据链路层, 也即 MAC层解决
MAC 的全称是 Medium Access Control,即媒体访问控制。
就是控制在往媒体上发数据的时候,谁先发、谁后发, 防止发生混乱。这解决的是第二个问题。这个问题中的规则,学名叫多路访问
1 2 3 方式一: 分多个车道。每个车一个车道,你走你的,我走我的。 ( 信道划分 ) 方式二: 今天单号出行,明天双号出行,轮着来 ( 轮流协议 ) 方式三: 不管三七二十一,有事儿先出门,发现特堵,就回去,错过高峰再出 ( 随机接入协议 ) ( 以太网就是这种 )
解决第一个问题: 发给谁? 谁接收? / 解决第三个问题: 发送出错怎么办?
这里用到一个物理地址,叫作链路层地址。但是因为第二层主要解决媒体接入控制的问题,所以它常被称为 MAC 地址
第二层的网络包格式
1 2 3 4 5 6 目标的 MAC 地址 源的 MAC 地址 类型: IP 数据包,然后 IP 里面包含 TCP、UDP,以及 HTTP 等,这都是里层封装的事情 ARP 数据包 CRC: 循环冗余检测
1 2 3 问题: 一个广播的网络里面接入了 N 台机器,我怎么知道每个 MAC 地址是谁呢? ARP 协议,也就是已知 IP 地址,求 MAC 地址的协议 发送一个广播包,谁是这个 IP 谁来回答。 为了避免每次都用 ARP 请求,机器本地也会进行 ARP 缓存, 机器会不断地上线下线,IP 也可能会变,所有缓存需要过期
局域网
Hub 是广播的,不管某个接口是否需要,所有的 Bit 都会被发送出去,然后让主机来判断是不是需要
机器少没问题,多了冲突概率就高, 而且把不需要的包转发过去,纯属浪费
每个口都只连接一台电脑,这台电脑又不怎么换 IP 和 MAC 地址,只要记住这台电脑的 MAC 地址,如果目标 MAC 地址不是这台电脑的,这个口就不用转发了。
1 2 3 4 5 6 例: MAC1 电脑将一个包发送给 MAC2 电脑 一开始交换机也不知道 MAC2 的电脑在哪个口,所以没办法,它只能将包转发给除了来的那个口之外的其他所有的口 但是,这个时候,交换机会记住这个口 MAC1 的, 以后有包的目的地址是 MAC1 的,直接发送到这个口就可以了。 交换机学习的结果称为 转发表: 有过期时间 ( 因为地址会变 )
小结 1 2 3 MAC 层是用来解决多路访问的堵车问题的 ARP 是通过吼的方式来寻找目标 MAC 地址的,吼完之后记住一段时间,这个叫作缓存; 交换机是有 MAC 地址学习能力的,学完了它就知道谁在哪儿了,不用广播了
交换机与VLAN:办公室太复杂,我要回学校 拓扑结构 1 2 办公室,整个公司多个楼层,几百个网口。 一台交换机肯定不够了,需要多台交换机, 然后交换机连起来, 就形成了稍微复杂的拓扑结构
当两个交换机将两个局域网同时连接起来的时候
1 2 刚开始机器 1 访问机器 2, 广播 ARP 包 这个包会在环路里转来转去, 多个机器都发广播包,广播包越来越多。 按上面共享道路的算法,也就是路会越来越堵,最后谁也别想走
1 2 3 4 数据结构中,有一个方法叫做最小生成树。有环的我们常称为图。将图中的环破了,就生成了树 在计算机网络中,生成树的算法叫作 STP,全称 Spanning Tree Protocol 理解: 华山论剑,最终决出五岳盟主
STP中的概念
1 2 3 4 5 6 Root Bridge: 根交换机, 树的老大 Designated Bridges: 指定交换机, 理解: 我拜谁做大哥,指定我的小弟也拜这个为大哥 Bridge Protocol Data Units (BPDU): 网桥协议数据单元, 理解为 “相互比较实力”的协议 Priority Vector: 优先级向量。 可以比喻为实力 (值越小越牛) [Root Bridge ID, Root Path Cost, Bridge ID, and Port ID] 实力比较: 先看Root Bridge ID (老大的实力), 再比 Root Path Cost(跟老大的关系远近) , 最后 Bridge ID(自己的实力)
STP 工作过程
1 2 3 4 5 1. 一开始,江湖纷争,异常混乱。大家都觉得自己是掌门,谁也不服谁。于是,所有的交换机都认为自己是掌门 2. 但每个网桥都会被分配一个ID, 网络管理员知道哪些交换机贵,哪些交换机好,就会给它们分配高的优先级, 即有些交换机生下来实力就强 3. 开始互相发送 BPDU 来比功夫 4. 赢的接着当掌门,输的做小弟。 掌门继续发BPDU, 小弟就没机会了。 只有在收到掌门发的 BPDU 的时候,转发一下,表示服从命令。 5. 出现了很多小的门派,然后小的门派,接着合并, 最后生成一棵树,武林一统
1 2 广播问题(性能): 机器多了,交换机也多了,就算交换机比 Hub 智能一些,但是还是难免有广播的问题。 广播一大堆,性能就下来了 安全问题: 由于在同一个广播域里面,很多包都会在一个局域网里面飘啊飘,碰到了一个会抓包的程序员,就能抓到这些包,如果没有加密,就能看到这些敏感信息了
办法一、 物理隔离
1 2 3 每个部门有单独的交换机,配置单独的子网,这样部门之间的沟通就需要路由器了 问题: 每个部门有单独的交换机,口多了浪费,少了又不够用。
办法二、 虚拟隔离 ( VLAN, 虚拟局域网 )
使用 VLAN,一个交换机上会连属于多个局域网的机器,那交换机怎么区分哪个机器属于哪个局域网呢?
在原来的二层 MAC的头上加一个 TAG,里面有一个 VLAN ID,一共 12 位
1 2 3 4 5 6 只要买的交换机是支持 VLAN的,当这个交换机把二层的头取下来的时候,就能够识别这个 VLAN ID。 可以设置交换机每个口所属的 VLAN 这样只有相同 VLAN 的包,才会互相转发,不同 VLAN 的包,是看不到的。这样广播问题和安全问题就都能够解决了 交换机之间怎么连接呢? 设置为 Trunk 口, 转发属于任何 VLAN 的口
ICMP与ping:投石问路的侦察兵
ICMP 全称 Internet Control Message Protocol,就是互联网控制报文协议。 ICMP 报文是封装在 IP 包里面的
ICMP 的格式
1 2 网络包在复杂网络环境中传输遇到问题的时候,不能“死个不明不白”,要传出消息来,报告情况 ICMP 常用类型: 主动请求为 8,主动请求的应答为 0
1 2 3 4 5 6 7 8 主动查询网络状况 ping 就是查询报文,是一种主动请求,并且获得主动应答的 ICMP 协议。在后面增加了自己的格式 对 ping 的主动请求,进行网络抓包,称为 ICMP ECHO REQUEST。同理主动请求的回复,称为ICMP ECHO REPLY 多了两个字段: 标识符: 理解: 两队侦查兵,一队是侦查战况的,一队是去查找水源 序号: 对派出去的包编号,回来多网络好,回来少网络差 在选项数据中: ping 还会存放发送请求的时间值,来计算往返时间,说明路程的长短
ping:查询报文类型的使用
1 在ping中间的设备或者路由, 使用 tcpdump -i eth0 icmp 可以查看包有没有到达这个点
1 2 3 4 5 6 7 8 9 10 异常情况发起的,来报告发生了不好的事情 例: 终点不可达为 3 具体原因在代码中: 网络不可达代码为 0,主机不可达代码为 1,协议不可达代码为 2,端口不可达代码为 3,需要进行分片但设置了不分片位代码为 4 源抑制为 4 让源站放慢发送速度 超时为 11 超过网络包的生存时间还是没到 重定向为 5 让下次发给另一个路由器 (更优路径)
Traceroute:差错报文类型的使用
1 2 3 4 5 6 7 8 9 10 11 12 13 可故意设置一些能够产生错误的场景 Traceroute 的第一个作用就是故意设置特殊的 TTL,来追踪去往目的地时沿途经过的路由器 设置为1, 即到达第一个路由或关卡就失败, 设置为2,3,最终获得中间所有路由 (公网路由都设置不会回这个ICMP,所有拿不到公网的) 如何查看UDP报文有没有到达目的主机? 发送UDP 数据报给目的主机,选择一个不可能的UDP 端口号(大于 30000) 如果到达目的主机返回端口不可达, 没到返回超时 Traceroute 还有一个作用是故意设置不分片,从而确定路径的 MTU 首先是发送分组,并设置“不分片”标志 发送的第一个分组的长度正好与出口 MTU 相等 如果中间遇到窄的关口会被卡住,会发送 ICMP 网络差错包,类型为“需要进行分片但设置了不分片位”。每次收到 ICMP“不能分片”差错时就减小分组的长度,直到到达目标主机。
出网关 1 2 3 4 5 6 7 8 9 上网: 在进行网卡配置的时候,除了 IP 地址,还需要配置一个Gateway网关 在任何一台机器上,当要访问另一个 IP 地址的时候,都会先判断目标 IP 地址,和当前机器的 IP 地址,是否在同一个网段? 判断网段是否一样: 需要 CIDR 和子网掩码 同一网段: 直接将源/目标地址放入 IP 头中,然后通过 ARP 获得 MAC 地址,将源/目的 MAC 放入 MAC 头中,发出去就可以了 不同网段: 发往默认网关。Gateway 的地址一定是和源 IP 地址是一个网段的 网关往往是一个路由器,是一个三层转发的设备: 就是把 MAC 头和 IP 头都取下来,然后根据里面的内容,看看接下来把包往哪里转发的设备
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 路由器: 多个网卡,连着多个局域网,每个网卡跟一个局域网网段相同, 一个数据包从一个口进来从哪个口出去,根据路由算法 路由分为: 静态路由, 动态路由 静态路由: 就是在路由器上配置 一条条匹配规则, 从哪个口出去是什么地址。 ``` - IP 头和 MAC 头哪些变、哪些不变 ? 两种类型网关 ```text MAC 地址是一个局域网内才有效的地址 MAC 地址只要过网关,就必定会改变,因为已经换了局域网 主要看IP是否变? IP地址不变的网关: 转发网关 而IP地址变的网关: NAT网关
转发网关
1 局域网之间的网段不会冲突, 即源/目标IP 不可能重复, 所以只需要 MAC地址修改进行转发
NAT网关 (Network Address Translation)
1 2 3 4 5 6 7 8 局域网之间,各定各的网段, IP冲突。 如上两天服务器的IP地址是相同的 解决: 既然局域网之间没有商量过,各管各的。 那到国际上,也即中间的局域网里面,就需要使用另外的地址,就想出国,不用身份证,用护照 例: 服务器 A 的国际身份是 192.168.56.1 , 服务器 B 的国际身份是 192.168.56.2 在网关上记录下身份, 出国就转换为国际身份,入国就转换为国内身份, 身份转换就是 NAT网关进行的IP转换
路由协议
1 2 3 4 5 6 7 8 路由表: 当一个入口的网络包送到路由器时,它会根据一个本地的转发信息库,来决定如何正确地转发流量。 路由规则 (至少包含三个信息): 1. 目的网络:这个包想去哪儿? 2. 出口设备:将包从哪个口扔出去? 3. 下一跳网关:下一个路由器的地址。 核心思想: 根据目的 IP 地址来配置路由
在真实的复杂的网络环境中, 根据多个参数来配置路由
1 2 3 可以配置多个路由表 可以根据源 IP 地址、入口设备、TOS 等选择路由表,然后在路由表中查找路由 这样可以使得来自不同来源的包走不同的路由
动态路由算法 1 2 3 4 5 6 7 8 使用动态路由路由器,可以根据路由协议算法生成动态路由表,随网络运行状况的变化而变化。 无论是一个国家内部,还是国家之间,我们都可以将复杂的路径,抽象为一种叫作图的数据结构 最终肯定是路越少越好,道路越短越好,因而这就转化成为如何在途中找到最短路径的问题。 最短路径常用的有两种方法: Bellman-Ford 算法 Dijkstra 算法
距离矢量路由( distance vector routing ) , 基于 Bellman-Ford 算法
1 2 3 4 5 6 7 8 9 基本思路: 每个路由器保存一个路由表,包含多行,每行对应网络中的一个路由器,包含两部分信息,一个是要到目标路由器,从那条线出去,另一个是到目标路由器的距离。 每个路由器知道全局信息: 每过几秒,每个路由器都将自己所知的到达所有的路由器的距离告知邻居,每个路由器也能从邻居那里得到相似的信息。 问题: 1. 好消息传得快,坏消息传得慢。 新路由器上线能很快通知邻居然后广播出去。 但路由挂了不会广播消息,当每个路由器发现原来的道路到不了这个路由器的时候,感觉不到它已经挂了,而是试图通过其他的路径访问,直到试过了所有的路径,才发现这个路由器是真的挂了。 2. 每次发送的时候,要发送整个全局路由表
链路状态路由算法(link state routing),基于 Dijkstra 算法
1 2 3 4 5 6 7 基本思路: 路由器启动,向邻居,发送一个 echo,要求马上返回,除以二就是距离。 然后将自己和邻居之间的链路状态包广播出去,发送到整个网络的每个路由器 然后每个路由器都能在自己本地构建一个完整的图, 然后针对这个图使用 Dijkstra 算法,找到两点之间的最短路径 链路状态路由协议只广播更新的或改变的网络拓扑 而且一旦一个路由器挂了,它的邻居都会广播这个消息,可以使得坏消息迅速收敛
路由协议
主要用在数据中心内部,用于路由决策 , 因而也称为内部网关协议(Interior Gateway Protocol,简称 IGP)。
1 2 OSPF(Open Shortest Path First,开放式最短路径优先) 多个最短的路径: 等价路由 ( 可进行负载均衡 )
外网路由协议(Border Gateway Protocol,简称 BGP)
使用 路径矢量路由协议(path-vector protocol), 是距离矢量路由协议的升级版
1 外网除了路径远近外,还有路过的不同数据中心不同policy的问题, 哪些IP能通过/不能通过。
AS ( Autonomous System ) 自治系统
1 2 3 Stub AS:对外只有一个连接。这类 AS 不会传输其他 AS 的包 (个人,小公司的网络) Multihomed AS:可能有多个连接连到其他的 AS,但是大多拒绝帮其他的 AS 传输包 ( 大公司网络 ) Transit AS:有多个连接连到其他的 AS,并且可以帮助其他的 AS 传输包 ( 主干网络 )
最重要的传输层
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 区别: TCP 是面向连接的,UDP 是面向无连接的 所谓的建立连接,是为了在客户端和服务端维护连接,而建立一定的数据结构来维护双方交互的状态,用这样的数据结构来保证所谓的面向连接的特性。 TCP: 提供可靠交付。 无差错、不丢失、不重复、并且按序到达。 面向字节流。 IP包是一个个包发的,变成流是TCP维护的 拥塞控制, 意识到自己包丢了或网络慢了,会调整自己的发送速度 是一个有状态服务 UDP: 不保证不丢失,不保证按顺序到达。 基于数据包,一个个收发 无状态服务 MAC 层定义了本地局域网的传输行为,IP 层定义了整个网络端到端的传输行为,这两层基本定义了这样的基因: 网络传输是以包为单位的,二层叫帧,网络层叫包,传输层叫段
UDP
包头: IP包送到某个地址, UDP则是送到某个端口
1 2 3 1. 沟通简单: 相信网络通路默认就是很容易送达的 2. 轻信他人: 不会建立连接,虽然有端口号,但是监听在这个地方,谁都可以传给他数据,他也可以传给任何人数据 3. 做事不变: 不管网络情况,该怎么发就怎么发
1 2 3 4 5 6 7 1. 需要资源少,在网络情况比较好的内网,或者对于丢包不敏感的应用 DHCP(内网获取IP地址,失败可重新来), TFTP 2. 不需要一对一沟通,建立连接,而是可以广播的应用 3. 需要处理速度快,时延低,可以容忍少数丢包,但是要求即便网络拥塞,也毫不退缩,一往无前的时候 要有自己的连接策略,应用层实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 1. 网页或者 APP 的访问 一般基于TCP的HTTP协议, QUIC(全称 Quick UDP Internet Connections,快速 UDP 互联网连接)是 Google 提出的一种基于 UDP 改进的通信协议,其目的是降低网络通信的延迟,提供更好的用户互动体验。 在应用层上,会自己实现快速连接建立、减少重传时延,自适应拥塞控制 2. 流媒体的协议 直播协议多使用基于 TCP 的 RTMP 但隔几个帧丢一个,其实看视频的人不会感知。因而,很多直播应用,都基于 UDP 实现了自己的视频传输协议。 3. 实时游戏 实时性比较高,采用自定义的可靠 UDP 协议,自定义重传策略,能够把丢包产生的延迟降到最低,尽量减少网络问题对游戏性造成的影响 4. IOT 物联网 资源少,维护 TCP 协议代价太大。 对实时性要求也很高。 5. 移动通信领域 移动流量上网的数据面对的协议 GTP-U 是基于 UDP 的
TCP
1 2 3 4 5 6 7 8 9 10 11 12 端口: 需要知道发给那个应用,应用监听端口 序号: 为了解决乱序 确认序号: 发出去的包应该有确认,没收到就重发。 不丢包 状态位: (TCP 是面向连接的,因而双方要维护连接的状态,这些带状态位的包的发送,会引起双方的状态变更) SYN 是发起一个连接 ACK 是回复 RST 是重新连接 FIN 是结束连接 窗口大小: 流量控制,通信双方各声明一个窗口,标识自己当前能够的处理能力,别发送的太快,也别发的太慢
1 2 3 4 5 顺序问题 丢包问题 连接维护 流量控制 拥塞控制
保证双方的消息有去有回就可以了
1 2 3 4 5 6 三次握手处理建立连接, 还沟通 TCP包的序号问题, 从哪个序号开始发送 每个连接都要有不同的序号。 这个序号的起始序号是随着时间变化的,可以看成一个 32 位的计数器,每 4 微秒加一, 如果计算一下,如果到重复,需要 4 个多小时,那个绕路的包早就死翘翘了, 因为我们都知道 IP 包头里面有个 TTL,也即生存时间
TCP 四次挥手
连接建立和断开的TCP状态机
TCP 如何实现靠谱?
1 2 3 为了保证顺序性,每一个包都有一个 ID 在建立连接的时候,会商定起始的 ID 是什么,然后按照 ID 一个个发送 为了保证不丢包,对于发送的包都要进行应答,不应答每个包,而是应答某个之前的 ID,表示都收到了,这种模式称为累计确认或者累计应答(cumulative acknowledgment)
发送端和接收端分别都有缓存来保存这些记录(所有发送和接收的包)
1 2 3 4 5 6 7 8 9 10 发送端, 按照包的 ID 一个个排列, 分四部分 1. 发送了并且已经确认 2. 发送但尚未确认 3. 未发送但等待发送 4. 未发送且暂时不会发送 流量控制: 接收端会给发送端报一个窗口的大小,叫 Advertised window 窗口的大小 等于 上面的第二,三部分。 而第四部分就是超过窗口不能发送的
1 2 3 4 5 6 7 8 9 10 11 接收端, 三部分 1. 接受并且确认过的 2. 还没接收,但是马上就能接收的。 即 能够接受的最大工作量 3. 还没接收,也没法接收的。 即 超过工作量的 第一,二 部分加起来是 接收端能接收的最大数量 第一部分是 已接收确认并确认,但未被应用使用的 第二部分就是 能接收的最大工作量, 即发送给接收端的 Advertised window 在第二部分中, 收到的包可能不是按顺序的,所以只有和第一部分连续的包可以进行马上回复,如果来的包不连续需要等待
1 2 3 4 5 6 7 8 9 10 确认重发机制 超时重传: 每个发送但未ACK的包,有一个定时器,超时就进行重新尝试 超时时间的确定: 必须大于往返时间 RTT 自适应重传算法(Adaptive Retransmission Algorithm): 估计往返时间,需要 TCP 通过采样 RTT 的时间,然后进行加权平均,算出一个值,而且这个值还是要不断变化的,因为网络状况不断地变化。除了采样 RTT,还要采样 RTT 的波动范围,计算出一个估计的超时时间 TCP的策略: 超时 间隔加倍。每当遇到一次超时重传的时候,都会将下一次超时时间间隔设为先前值的两倍。两次超时,就说明网络环境差,不宜频繁反复发送
1 2 3 4 5 接收方在对于包的确认中,同时会携带一个窗口的大小 极端情况,接收端的应用一直不读取缓存中的数据,则随着确认的包越来越多,窗口越来越小,直到为 0 发送方会定时发送窗口探测数据包,看是否有机会调整窗口的大小。 而发送方不是空出一字节就马上调整的, 是达到一定大小才更新窗口
1 2 3 4 5 6 7 8 9 也是通过窗口的大小来控制的: 前面的滑动窗口 rwnd 是怕发送方把接收方缓存塞满 而拥塞窗口 cwnd,是怕把网络塞满 公式 LastByteSent - LastByteAcked <= min {cwnd, rwnd} ,是拥塞窗口和滑动窗口共同控制发送的速度。 通道的容量 = 带宽 × 往返延迟。 设置发送窗口,使得 发送但未确认的包 为通道的容量,就能够撑满整个管道 TCP 的拥塞控制主要来避免两种现象,包丢失和超时重传
cwnd 拥塞窗口的慢启动
1 2 3 4 5 6 一条 TCP 连接开始: cwnd设置为1, 一次只能发送一个, 然后收到每个确认加1, 即下次2个,然后2个确认变4,然后变8,指数增长 指数增长到 ssthresh 的值, 就慢下来,每个确认增加 1/cwnd,即每次所有确认收到后加一,变成线性增长 线性增长最终出现拥塞即出现丢包现象,降低速度。 一种是: 将 sshresh 设为 cwnd/2,将 cwnd 设为 1,重新开始慢启动。 太激进,高速传输一下停止,容易网络卡顿 二种是: 将cwnd 减半为 cwnd/2,然后 sshthresh = cwnd。 还在比较高的值,呈线性增长
1 2 3 4 5 6 TCP 拥塞控制的问题 1.丢包并不代表着通道满了,也可能是管子本来就漏水。 如公网网络状况不好,这个时候就认为拥塞了,速度降低是不对的 2. TCP 的拥塞控制要等到将中间设备的缓存都填充满了,才发生丢包,从而速度降低。 TCP 只要填满管道就可以了,不应该接着填 为了优化这两个问题,后来有了 TCP BBR 拥塞算法
基于 TCP 和 UDP 协议的 Socket 编程 1 2 3 4 5 分客户端和服务端, 理解为一根网线,一头插在客户端,一头插在服务端,然后进行通信。 在通信之前,双方都要建立一个 Socket。 参数设置: 指定是 IPv4 还是 IPv6,分别对应设置为 AF_INET 和 AF_INET6 指定是 TCP 还是 UDP, 分别对应 基于数据流SOCK_STREAM 和 基于数据报SOCK_DGRAM
基于 TCP 协议的 Socket 程序函数调用过程 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 服务端socket: 先 bind 进行绑定 IP地址和端口 listen 进行监听 内核维护两个队列: 1. 已经建立了连接的队列 , 已完成三次握手, 处于 established 状态 2. 还没有完全建立连接的队列, 处于三次握手中, 处于 syn_rcvd 的状态 调用 accept 函数,拿出一个已经完成的连接进行处理 客户端socket: 在服务端进入listen状态后, 可以使用 connect 发起连接(指明连接IP和端口),进行三次握手 内核给客户端分配一个临时端口 握手成功,服务端的 accept 就会返回另一个 Socket 注意: 监听的 Socket 和真正用来传数据的 Socket 是两个: 监听socket, 已连接socket 两端连接建立后: 双方都通过 read, write 进行读写数据, 像文件流读写一样
1 2 3 4 5 6 7 8 9 10 11 12 Socket 在 Linux 中就是以文件的形式存在的 存在文件描述符。写入和读出,都是通过文件描述符 每一个进程都有一个数据结构 task_struct,里面指向一个文件描述符数组,来列出这个进程打开的所有文件的文件描述符。 文件描述符是一个整数,是这个数组的下标。 内容是指针,指向文件地址 一个文件,就会有一个 inode 只不过 Socket 对应的 inode 不像真正的文件系统一样,保存在硬盘上的,而是在内存中的。 在这个 inode 中,指向了 Socket 在内核中的 Socket 结构 socket 结构: 主要是两个队列 - 发送队列 和 接收队列 在这两个队列里面保存的是一个缓存 sk_buff。这个缓存里面能够看到完整的包的结构。 用于收发包
基于 UDP 协议的 Socket 程序函数调用过程 1 2 3 4 5 UDP 没有连接,不需要三次握手,也就不需要调用 listen 和 connect 但是,UDP 的交互仍然需要 IP 和端口号,因而也需要 bind。 UDP 没有维护连接状态,因而不需要每对连接建立一组 Socket,而是只要有一个 Socket,就能够和多个客户端通信。 也正因为没有连接状态,每次通信的时候,都调用 sendto 和 recvfrom,都可以传入 IP 地址和端口。
服务器如何接更多的项目?
一个四元组 标识 一个 TCP 连接:
{本机IP, 本机端口, 对端IP, 对端端口}
1 2 3 4 5 6 对服务端来说: 最大 TCP 连接数 = 客户端 IP 数×客户端端口数 对 IPv4,客户端的 IP 数最多为 2 的 32 次方,客户端的端口数最多为 2 的 16 次方,也就是服务端单机最大 TCP 连接数,约为 2 的 48 次方。 实际限制: 1. 文件描述符限制: Socket 都是文件,所以首先要通过 ulimit 配置文件描述符的数目; 2. 内存:每个 TCP 连接都要占用一定内存
在资源有限的情况下,如何降低每个连接消耗的资源数目。达到更多的连接数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 1. 多进程方式 (将项目外包给其他公司) 一旦建立了一个连接,就会有一个已连接 Socket,这时候你可以创建一个子进程,然后将基于已连接 Socket 的交互交给这个新的子进程来做 Linux 下,创建子进程使用 fork 函数。这是在父进程的基础上完全拷贝一个子进程。 在 Linux 内核中,会复制文件描述符的列表,也会复制内存空间,还会复制一条记录当前执行到了哪一行程序的进程。 显然,复制的时候在调用 fork,复制完毕之后,父进程和子进程都会记录当前刚刚执行完 fork。这两个进程刚复制完的时候,几乎一模一样,只是根据 fork 的返回值来区分到底是父进程,还是子进程。如果返回值是 0,则是子进程;如果返回值是其他的整数,就是父进程。 复制了文件描述符列表,而文件描述符都是指向整个内核统一的打开文件列表的, 子进程直接就可以通过这个已连接 Socket 和客户端进行互通 最后子进程通信完成,父进程根据子进程ID查看是否退出子进程 2. 多线程方式(将项目转包给独立的项目组) 在 Linux 下,通过 pthread_create 创建一个线程,也是调用 do_fork 但很多资源,例如文件描述符列表、进程空间,是共享的,只不过多了一个引用而已。 新的线程也可以通过已连接 Socket 处理请求,从而达到并发处理的目的 上面两种问题: 每次新到来一个 TCP 连接,就需要分配一个进程或者线程 一台机器无法创建很多进程或者线程。有个 C10K 问题 3. IO 多路复用,一个线程维护多个 Socket (一个项目组支撑多个项目) 某个线程盯的所有的 Socket,都放在一个文件描述符集合 fd_set 中 然后调用 select 函数来监听这个文件描述符集合是否有变化。 一旦有变化,就会依次查看每个文件描述符。 那些发生变化的文件描述符在 fd_set 对应的位都设为 1,表示 Socket 可读或者可写,从而可以进行读写操作, 然后再调用 select,接着盯着下一轮的变化。 4. IO 多路复用,从“派人盯着”到“有事通知” (一个项目组支撑多个项目) 上面第三种方法,select查询集合的问题: Socket文件描述符集合中有发生变化时,采用轮询的方法需要将整个集合过一遍,这样效率太低,影响线程能处理的最大socket数量 因而使用 select,能够同时盯的项目数量由 FD_SETSIZE 限制 改进: 改成事件通知的方式, 能完成这件事情的函数叫 epoll,它在内核中的实现不是通过轮询的方式,而是通过注册 callback 函数的方式,当某个文件描述符发送变化的时候,就会主动通知 进程打开了多个 socket 文件描述符, epoll_create 创建一个 epoll 对象,也是个文件,内容是红黑树, 保存这个 epoll 监听的所有 Socket。 当 epoll_ctl 添加一个 Socket 的时候,其实是加入这个红黑树,同时红黑树里面的节点指向一个结构,将这个结构挂在被监听的 Socket 的事件列表中。当一个 Socket 来了一个事件的时候,可以从这个列表中得到 epoll 对象,并调用 call back 通知它。 使用这种方式, 能够同时监听的 Socket 的数目就非常的多了。上限就为系统定义的、进程打开的最大文件描述符个数 epoll 被称为解决 C10K 问题的利器。
应用层 HTTP 数据中心 DNS协议, 网络世界的地址簿
1 2 3 4 5 6 DNS 服务器,一定要设置成高可用、高并发和分布式的 分为三层: 根 DNS 服务器: 返回顶级域 DNS 服务器的 IP 地址 顶级域 DNS 服务器: 返回权威 DNS 服务器的 IP 地址 权威 DNS 服务器 :返回相应主机的 IP 地址
1 2 3 4 1. 先访问 本地域名服务器 (如移动电信等网络服务商的机房) 2. 本地域名服务器 找到直接返回IP, 没找到则访问 根域名服务器(全球共 13 套。它不直接用于域名解析,返回顶级域名服务器地址) 3. 本地域名服务器 访问 顶级域名服务器( 也不直接域名解析,返回权威域名服务器的地址 ) 4. 本地域名服务器 访问 权威域名服务器 ( 进行域名解析查询到对应的IP返回 )
内部负载均衡
1 2 3 多个应用访问一个数据库: 如果配置IP,IP换了就需要所有应用修改配置, 如果配置了域名,只需要将域名映射为新的IP A应用访问应用B, 如果应用B撑不住了,可以集群部署,域名配置对应多个应用B的IP,配置域名解析的策略,进行负载均衡
全局负载均衡
1 2 3 4 5 基于 DNS 的全局负载均衡: 用来选择一个就近的同样运营商的服务器进行访问 可以再DNS服务器中配置 CNAME, 给域名起别名,让本地DNS服务器请求 转到 全局负载均衡器(GSLB: Global Server Load Balance) 进行更复杂的解析 可配置第一层 GSLB,解析跟本地DNS服务器相同的运营商, 然后再这个GSLB 同样配置 CNAME, 转到第二层GSLB 在第二层 GSLB, 解析本地DNS服务器就近的地址, 返回给本地DNS服务器,相同运营商的最近的服务器IP地址
域名缓存问题
1 本地服务器 对已经访问过的地址有缓存, 域名换地址后可能还是导向旧地址
域名转发问题
1 2 有些小的运营商不是直接自己访问权威域名服务器 ,而只是进行转发,让其他大的运营商进行域名解析 就会导致: A运营商的请求,最后是B运营商访问域名服务器进行域名解析,最后返回B运营商的IP, 导致每次请求都跨运营商, 很慢
出口 NAT 问题
1 2 网络出口的时候,很多机房都会配置 NAT,也即网络地址转换,使得从这个网关出去的包,都换成新的 IP 地址 权威DNS服务器,就没办法通过这个地址,来判断客户到底是来自哪个运营商, 可能导致误判运营商,最终跨运营商访问,速度慢
域名更新问题
1 2 本地 DNS 服务器是由不同地区、不同运营商独立部署的 在权威 DNS 服务器解析变更的时候,解析结果在全网生效的周期非常漫长
解析延迟问题
1 DNS 的查询过程需要递归遍历多个 DNS 服务器, 会有时延
HttpDNS
就是不走传统的 DNS 解析, 而是自己搭建基于 HTTP 协议的 DNS 服务器集群,分布在多个地点和多个运营商。当客户端需要 DNS 解析的时候,直接通过 HTTP 协议进行请求这个服务器集群,得到就近的地址。
1 httpDNS需要绕过传统DNS, 不使用默认客户端,往往是手机应用,嵌入支持HttpDNS的客户端
1 2 3 4 5 6 在客户端的 SDK 里动态请求服务端,获取 HttpDNS 服务器的 IP 列表,缓存到本地 随着不断地解析域名,SDK 也会在本地缓存 DNS 域名解析的结果。 这个缓存是手机应用自己的,可以自己协调 过期更新时间等 手机客户端自然知道手机在哪个运营商、哪个地址。由于是直接的 HTTP 通信,HttpDNS 服务器能够准确知道这些信息,因而可以做精准的全局负载均衡。
CDN 1 2 3 4 5 6 7 8 9 10 11 参考思路: 物流的 "就近配送",在电商网站下单,不是从总部发送快递,从就近仓库发送。 在全球这么多数据中心里部署几台机器,形成一个缓存的集群来缓存部分数据,让用户访问时可以就近访问 分布在各个地方的各个数据中心的节点,称为 边缘节点 边缘集群规模比较小,不可能缓存下来所有东西,因而可能无法命中 边缘节点之上是: 区域节点 再之上是: 中心节点 最后还没有就是去 源网站 访问了 CDN分发系统架构: 中心节点 -》 区域节点 -》 边缘节点
1 2 3 4 5 6 7 跟DNS的全局负载均衡器很像。 在整个多区域,多运营商的分发网络下,找到就近的节点 设置了CDN的访问请求: 1. 访问请求网址, 进行第一步域名解析,网址权威DNS服务器上,设置 CNAME,返回CND网络的域名 2. 去 CDN网络域名的 权威DNS服务器上,在这个权威DNS服务器上,设置 CNAME,返回CND的全局负载均衡解析器 3. 去 全局负载均衡解析器, 根据 全局负载均衡器内的策略, 返回合适的缓存服务器。
1 2 3 4 比较容易缓存,不容易过期 静态页面, 图片等 流媒体协议: 大量采用了CDN
数据中心 VPN
Virtual Private Network,虚拟专用网
1 2 3 4 5 6 7 两个数据中心连接 走公网不安全 租用专线连接太贵 折中办法VPN: 利用开放的公众网络,建立专用数据传输通道,将远程的分支机构、移动办公人员等连接起来 VPN 通过隧道技术在公众网络上仿真一条点到点的专线,是通过利用一种协议来传输另外一种协议的技术 这里面涉及三种协议:乘客协议、隧道协议和承载协议
IPsec VPN ( 基于 IP 协议的安全隧道协议 )
1 2 3 4 5 6 1. 公网上信息安全的保证机制 私密性: 加密, 对称加密 完整性: 数据没有被非法篡改,通过对数据进行 hash 运算,产生类似于指纹的数据摘要 真实性: 数据确实是由特定的对端发出,通过身份认证可以保证数据的真实性。
移动网络 云计算中的网络 云中网络 1 2 从物理机到虚拟机: 软件模拟硬件, 主要模拟 CPU、内存、网络、硬盘 在数据中心里,用的是 qemu-kvm
1 2 3 4 5 6 7 qemu-kvm 使用 linux中的 TUN/TAP 技术 虚拟机 是软件: 打开一个称为 TUN/TAP 的 Char Dev(字符设备文件), 在物理机上就能看到一张虚拟 TAP 网卡。 虚拟机会将打开的这个文件在内部虚拟出一个网卡,所有网络包都往这里发,虚拟机会将网络包转换成为文件流,写入字符设备,就像写入文件一样 内核中 TUN/TAP 字符设备驱动会收到这个写入的文件流,交给 TUN/TAP 的虚拟网卡驱动。 这个驱动将文件流再次转成网络包,交给 TCP/IP 协议栈,最终从虚拟 TAP 网卡发出来,成为标准的网络包。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 云计算中的网络注意点: 共享: 每个虚拟机一个或多个虚拟网卡,但物理机上只有有限几个网卡,多虚拟网卡如何共享同一个出口? 隔离: 安全隔离-两个虚拟机两个用户 , 流量隔离-两个虚拟机,一个疯狂下载另一个直接没网 互通: 一个用户两天虚拟机,在一个物理机或两个物理机, 如何通信? 灵活: 虚拟机可能经常创建删除,在不同物理机上飘,有的互通有的不同,需要灵活配置 共享和互通问题: 理解物理机是大学宿舍,虚拟机是个人电脑,之间连通需要交换机 虚拟的交换机: Linux 上的命令 brctl, 创建虚拟网桥brctl addbr br0,然后将两个虚拟机的虚拟网卡连接到这个网桥,网段一致就可以通信了 虚拟机连接外网: 桥接: 将物理网卡 也连接到虚拟交换机上, 跟内部虚拟机的虚拟网卡处于同一网段 NAT: 虚拟交互机和物理网卡之间 有一个NAT设备, 虚拟网络 和 物理网络 不是同一个网络, 还会内置一个虚拟DHCP服务器,为虚拟机分配IP 隔离问题: 1. 一台机器上的两个虚拟机不属于同一个用户, 进行隔离? brctl 创建的网桥也是支持 VLAN 功能的 设置两个虚拟机的 tag,这样在这个虚拟网桥上,两个虚拟机是不互通的。 2. 跨物理机互通,并且实现 VLAN 的隔离呢? 命令 vconfig,可以基于物理网卡 eth0 创建带 VLAN 的虚拟网卡, 所有从这个虚拟网卡出去的包,都带这个 VLAN 为每个用户分配不同的 VLAN,在物理机上,基于物理网卡,为每个用户用 vconfig 创建一个带 VLAN 的网卡 不同的用户使用不同的虚拟网桥,带 VLAN 的虚拟网卡也连接到虚拟网桥上。
软件定义网络 ( SDN )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 控制和转发分离 控制平面与转发平面之间的开放接口 逻辑上的集中控制 ``` - 实现 ( openFlow, openvSwitch ) ```text OpenFlow 是 SDN 控制器和网络设备之间互通的南向接口协议 OpenvSwitch 用于创建软件的虚拟交换机, 支持 openFlow协议 硬件交换机也支持 openFlow协议,从而实现 虚拟机和物理机 被SDN统一控制网络物理 SDN 控制器是如何通过 OpenFlow 协议控制网络的呢? 在 OpenvSwitch 里面,有一个流表规则,任何通过这个交换机的包,都会经过这些规则进行处理,从而接收、转发、放弃 流表: 多个表格,每个表格多行, 每一行 ( 匹配规则,优先级,执行动作 ) 规则覆盖 TCP/IP 协议栈的四层 物理层: 匹配规则: 从哪个口进来 执行动作: 从哪个口出去 MAC层: 匹配规则: 源/目标 MAC 地址, 所属 VLAN 执行动作: 修改 源/目标 MAC 地址, 修改,删除 VLAN, MAC地址学习 网络层: 匹配规则: 源/目标 IP地址 执行动作: 修改 源/目标 IP地址 传输层: 匹配规则; 源/目标 端口 执行动作: 修改 源/目标 端口
网络安全 1 2 3 共有云上的端口的 安全守护措施: 采用 ACL(Access Control List,访问控制列表)来控制 IP 和端口 设置规则,指定IP可以访问开放接口 - 安全组
网络包进入机器后的流程
1 2 3 4 5 6 1. 拿下MAC头,查看是否是自己的,是就继续 2. 拿下IP头,获取其中的目标IP, 开始进行路由判断,判断之前的节点称为: PREROUTING(路由之前) 3. 如果IP是自己的,发给上面的传输层, 这个节点称为: INPUT 4. 如果不是自己的,转发出去, 这个几点称为: FORWARD 5. 上传处理完成会返回一个处理结果,处理结果会发出去,这个节点称为: OUTPUT 6. 转发还是发出去, 都是在路由判断之后,最后一个节点为: POSTROUTING
上诉五个重要节点:
1 2 3 linux内核,框架Netfilter, 可以在这些节点插入hook函数,截获数据包,对数据包进行干预 一个著名的实现: ip_tables 按功能可分为四大类:连接跟踪(conntrack)、数据包的过滤(filter)、网络地址转换(nat)和数据包的修改(mangle)
1 2 3 在云上每个虚拟机都自己安装iptables然后设置规则过于麻烦 所以在云平台上,一般允许一个或者多个虚拟机属于某个安全组, 而属于不同安全组的虚拟机之间的访问以及外网访问虚拟机,都需要通过安全组进行过滤
云中的网络 Qos (Quality of Service) 1 2 3 网络控制: 进入的方向不能控制,只能通过policy进行丢弃 出去的方向可以控制
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 主要都是通过队列的方式进行控制 一.无类别排队规则 1. pfifo_fast 分为三个优先级的 先入先出队列Band, 根据网络包里面 TOS,判断进入哪个队列。 TOS 4位 16种类型,对应到 三个队列中 2. 随机公平队列 (Stochastic Fair Queuing) 建立很多的 FIFO 的队列,TCP Session 计算 hash 值,根据hash值分配队列, 另一边轮询从队列中拿数据包发送 3. 令牌桶规则 (TBF,Token Bucket Filte) 一个FIFO队列,但需要拿令牌才能发送 二. 基于类别的队列规则 1. 分层令牌桶规则(HTB, Hierarchical Token Bucket)
1 2 对于进入的流量,可以设置策略 Ingress policy 对于发出的流量,可以设置 QoS 规则 Egress shaping,支持 HTB
容器技术中的网络 容器网络
看起来是隔离的技术: namespace (命名空间)
1 2 3 将全局性的内容,以命名空间隔离进行不重复。 网络的 namespace 由 ip netns 命令操作。它可以创建、删除、查询 namespace
用起来是隔离的技术: cgroup (control groups)
1 2 3 4 是 Linux 内核提供的一种可以限制、隔离进程使用的资源机制。