概述

将计算机(网络)互相连接起来要使用一些中间设备,ISO的术语称之为中继(relay)系统。根据中继系统所在的层次,可以有以下五种中继系统:

  • 物理层(即常说的第一层、L1)中继系统,即转发器(repeater/hub)。
  • 数据链路层(即第二层,L2),即网桥或桥接器(bridge)。
  • 网络层(第三层,L3)中继系统,即路由器(router)。
  • 网桥和路由器的混合物桥路器(brouter)兼有网桥和路由器的功能。

交换

“交换”是一个涵义广泛的词语,从电路交换到分组交换,无论何种场合都可将其套用,搞不清到底什么才是真正的交换。从本意上来讲,交换只是一种技术概念,即完成信号由设备入口到设备出口的转发。因此,只要是和符合该定义的所有设备都可被称为交换设备。

我们经常说到的以太网交换机实际是一个基于网桥技术的多端口第二层网络交换设备,它为数据帧从任意一个端口到另一个任意端口的转发提供了低时延、低开销的通路。

层1交换机(中继器/集线器)

常用的网络拓扑有星形和总线形,这两种拓扑结构从逻辑上来说都归于总线形。只要其中一台主机发出信息,集线器会把信息复制给其他的所有端口的主机,集线器也被称为多端口中继器。

我们称连接到一个集线器的所有主机共享一个冲突域。即各主机发出的物理信号都在总线上传输而在时域上发生冲突。

从数据包角度,集线器上的主机可以抓到在总线上所有没有发生冲突的包,而不需要数据链路层的信息。

层2交换机(网桥/桥接器)

太网第二层交换机是基于多端口网桥发展而来,工作于数据链路层,其内部核心处有一个交换矩阵(MAC地址<->物理端口表),可以为任意两端口间的通信提供通路,以使一端口接收的数据帧从另一端口送出。

  • 当交换机从某个端口收到一个数据包,它先读取包头中的源MAC地址,这样它就知道源MAC地址的机器是连在哪个端口上;
  • 再去读取包头中的目的MAC地址,并在地址表中查找相应的端口;
  • 如表中有与这目的MAC地址对应的端口,把数据包直接复制到这端口上。

从上面的过程可以看出,层2交换机的工作原理很像一座“平转桥”:将源MAC->目的MAC的链路接通,而把其它链路断开,所以叫网桥或桥接器。层2交换机每条链路都是一个单独的冲突域,也意味着每条链路不共享带宽。

从数据包角度,层2交换机上的主机只能抓到源/目的地址是自己的包,而不会收到除此以外的数据包。

层3路由器

路由器工作于网络(IP)层,其内部核心有一个路由表,路由器的基本功能是把数据(IP报文)传送到正确的网络,包括:

  • IP数据报的转发,包括数据报的寻径和传送;
  • 子网隔离,抑制广播风暴;
  • 维护路由表,并与其他路由器交换路由信息,这是IP报文转发的基础。
  • IP数据报的差错处理及简单的拥塞控制;
  • 实现对IP数据报的过滤和记帐。

它首先把链路层的包头去掉(拆包),读取目的IP地址,然后查找路由表,若能确定下一步往哪送,则再加上链路层的包头(打包),把该数据包转发出去;如果不能确定下一步的地址,则向源地址返回一个信息,并把这个数据包丢掉。该过程由路由器的CPU进行处理。

层3交换机

很多场景同时需要层2交换机和层3路由器的功能,比如说4口家庭路由器(同时还有网关和NAT功能)。又比如说大型局域网的子网划分和互通,就形成了层3交换机。

层3交换机主要实现了VLAN之间的互通,层2交换机虽然也可以进行VLAN的划分,但是不能互通。那为什么要用交换机实现VLAN而不用路由器实现LAN呢?这更多的是从性能角度考虑的。路由器的转发工作是由CPU进行的,性能较差;层3交换机则直接由硬件实现,性能高。

网关

网关是独立于上述概念的一个概念,也和具体的层没有太大的关系(一般在3层)。它指明了一个包如果在一个子网中没有找到目标主机(根据各层的目标地址),则将这个包发送给默认网关,由网关决定这个包的处置。

IPv6中由于邻居发现,网关的概念被弱化了。

交换机下的UDP发包与抓包

linux下发包和抓包一般使用tcpdump工具集,其中tcpdump是命令行程序,libpcap是其开发库。

抓包(wireshark/tcpdump/libpcap)原理

  1. 同子网下:目的网卡必须在线,且只能是目的网卡抓包。
  2. 不同子网下:需要设置网关地址,目的地址不在同一网段;目的网卡不需要在线。 总结:交换机下的网络并非是环状网络,发出去的包不会传到其它计算机上,只会到达下一跳网卡(目的网卡或网关)

抓包需要的权限

linux下抓包需要cap_net_raw,cap_net_admin两个能力,可以通过如下命令赋予二进制可执行程序binary_exec抓包能力

1
sudo setcap cap_net_raw,cap_net_admin=eip binary_exec

当然也可以使用sudo binary_exec直接赋予root权限。

linux下发包/包注入暂时还不知道需要什么能力,很有可能只能用以root权限才行。