Reading view

There are new articles available, click to refresh the page.

绕过校园网分享限制,构建愉快的宿舍网络环境

最近大一新生们开学了,就有几位学弟来问我说,咱们学校的校园网要怎么才能开 WiFi 热点、能不能用路由器。回想一下当初我也折腾了好一段时间,本来想水篇博客的,后来不知道怎么的就咕咕咕了……正好借此机会分享一下。

其实吧,学校有的是办法搞你。除了强制一人一号、恶心的专用拨号客户端防共享以外,还能通过 IPID、TTL、时钟偏移检测,甚至是 DPI 深度包检测的方法来防私接,就看校方做得够不够绝了。当然破解的方法也有,但基本也不会让你好受。如果碰到这样的校园网,推荐你直接躺平,给这种垃圾网络交钱还不如开个无限流量套餐呢。

免责声明:日后你惹出祸来,不把师父说出来就行了.jpg

校园网的限制

先说一下我们学校校园网恶心的地方。接入网线后,你需要:

  1. 使用【软件A】进行第一次拨号:
    • 【软件A】会进行多网卡检测,如果你的系统里有一个以上的网络适配器,则拒绝拨号;
    • 上述网络适配器包括硬件网卡(USB 网卡、无线网卡)和虚拟网卡(各种虚拟机的虚拟网卡、TAP 网卡等);
    • 认证类型为 802.1x 认证。
  2. 使用【软件B】进行第二次拨号:
    • 【软件B】不检测网卡,但会拒绝在虚拟机中运行,如果宿主机开了 Hyper-V 还会误报;
    • 检测猎豹 WiFi、360 WiFi 等共享软件的进程;
    • 认证类型为 L2TP VPN。

而且这两个软件只能在 Windows 上跑,macOS、Linux 用户就干瞪眼吧。

其实说到这里,有些人应该都心里有数这俩软件是啥。不过我这里就不明说了,懂的都懂(x

接下来来看一下网上常见的破解方案,也就是路由器拨号

据说网上有很多人在卖所谓的「校园网路由器」,其实说白了就是刷了 OpenWRT 的路由器 + 破解校园网的插件。如果有现成的插件能用,那自然是最好,刷个固件也不是什么难事。但不幸的是,目前网上并没有针对【软件A】新版本的拨号脚本,而旧版本的已经不再适用于我们学校的网络了。除非另有大神愿意开发新版本的拨号脚本,否则这条路是行不通的。更何况我们这还要二次拨号,更是难上加难。

taobao-campus-routers

而如果想要在电脑上直接分享热点,第一会被检测多网卡,第二可能会被检测进程。

emmmmm……🤔

那么,让我们的网卡不被检测到不就行了?

使用虚拟机绕过网卡检测

这个方法其实是以前我偶然发现的。

当时我在用虚拟机捣鼓 Kali Linux,用了 VirtualBox 的 USB Passthrough 功能把 USB 外接网卡穿透进虚拟机给 Kali 使用。此时,宿主机操作系统里是看不见这个 USB 网卡的,设备管理器、网络适配器里都没有,就像不存在一样。不存在……嗯?

于是我翻箱倒柜找出了几年前凑单买的小米随身 WiFi,在虚拟机里一通操作:

vm-windows-xp-miwifi

嘿,成了!

如何配置,搜索「VirtualBox USB 网卡」即可。

看来虚拟机的 USB 直通确实可以避开校园网认证客户端的多网卡检测,而且客户端也并没有对 VirtualBox 做什么手脚(后来查了一下,据说【软件A】会干扰 VMware 的 NAT 网络共享服务……)。那么,能做的事情可就多了。

使用有线网卡桥接路由器

上面的方案能用是能用,但效率过于低下。

  1. 虚拟机系统没必要用 Windows,就算是 XP 也是性能浪费;
  2. USB 无线网卡孱弱的 WiFi 性能不足以满足我的需求;
  3. 每次开机都要启动虚拟机,操作繁琐复杂。

既然要用得爽,那肯定得把这些问题解决了。

首先,把 USB 无线网卡换成 USB 有线网卡,下联硬路由作为 AP。同时,把 Guest OS 换成轻量级的 Alpine Linux 并实现开机启动。完成后的网络拓扑图类似这样(综合考虑最后还是选择了两层 NAT):

network-topology

首先在虚拟机内安装 Alpine Linux 和对应的网卡驱动(注意不要用 virt 版本的内核,很多驱动都被精简掉了):

ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:002: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UP qlen 1000    link/ether [mac addr] brd ff:ff:ff:ff:ff:ff3: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UP qlen 1000    link/ether [mac addr] brd ff:ff:ff:ff:ff:ff4: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP qlen 1000    link/ether [mac addr] brd ff:ff:ff:ff:ff:ff

添加网桥,把 USB 网卡和虚拟机的虚拟网卡桥接到一起:

brctl addbr br0brctl addif br0 eth0brctl addif br0 eth1brctl show

启动网络:

ip link set dev eth1 upip link set dev br0 upip link show

删除之前分配给虚拟网卡 eth0 的 IP,并启动 DHCP 客户端为 br0 获取 IP 地址:

ip addr flush dev eth0udhcpc -i br0ip addr show

此时应该虚拟机内、有线网卡端都能访问网络了,可以通过 ping 测试一下。

可以用的话就永久保存网络配置:

vi /etc/network/interfaces
auto loiface lo inet loopbackauto br0iface br0 inet dhcp        hostname alpine-vm        bridge-ports eth0 eth1        bridge-stp 0

接下来把 USB 网卡和路由器的 WAN 口用网线连接起来,测试是否工作正常。如果想省一层 NAT,可以连到 LAN 口上并关闭路由器 DHCP 功能,就当个单纯的 AP 使用。不过我为了相对稳定的内网环境,还是选择了前者。

router-interfaces

一切正常的话,就可以愉快地使用 WiFi 啦。

如果想要让 Alpine 虚拟机开机后台运行,可以使用 VBoxHeadlessTray 这个程序。

virtualbox-alpine-booting

当前方案的不足之处

至此,我们的校园网网络共享方案已经算是比较完善了。

幸运的是,我校似乎并没有部署其他什么防私接技术,像这样用了半年多也一直相安无事,省下我不少流量费。

然而,这个方案还是有些不爽的地方。

  1. 作为主机的电脑和其他设备不在一个子网下;
  2. 电脑必须一直开着其他设备才能有网。

在这套方案下,路由器下联的设备对于主机是几乎不可见的(不然也绕不过校园网分享限制了)。你可以在其他设备上访问主机上的网络服务(VirtualBox 的 NAT 网络里宿主机的 IP 一般为 10.0.2.2,子网下的设备可以直接访问,效果和主机上访问 localhost 基本一致),但无法反过来访问子网里的其他设备。

虽然你也可以通过 VirtualBox 的端口映射实现一些变通的解决,比如把路由器的 22、80 端口映射到宿主机上方便访问,但 SMB 这类服务就不行了(Windows 访问 SMB 服务器时强制端口为 445,无法手动指定,要改只能改注册表),所以我完全无法在主机上访问子网下的 NAS 设备。

这也太难受了,继续改进!

既然这些软件都需要跑在一台 Windows 机器上,那我专门弄一台机器来跑校园网相关的东西不就好了吗?

入手双网口工控机软路由

于是我把目光投向了最近几年很火的软路由。

就像计算机有软件和硬件的区别,路由器也有「软」「硬」之分。通常我们在各个电商平台上搜索「路由器」这三个关键词所得到的几乎所有商品都属于硬路由,它是由路由器厂商基于自行开发或是开源的嵌入式设备操作系统,根据特定的硬件设备,设计出来的传统硬件设备。

而与之对应的软路由,是基于软件工具在普通的硬件上来实现传统路由器的功能。我们可以在旧电脑、工控机、开发板、服务器甚至是硬件虚拟机中安装软路由系统,然后通过强大的软件实现各种各样的功能。

——《从听说到上手,人人都能看懂的软路由入门指南》

一番比较后,我在某鱼上入手了一台二手的双网口工控机,安装 Windows 7 系统后,将上面的所有校园网相关的软件都转移到了这台低功耗小主机上。

至于为什么买双网口的机器,虽然 VirtualBox 只能直通 USB 网卡所以还是得外接,不过考虑到以后不用校园网了还可以原地变身软路由,所以不如直接一步到位买个好点的。毕竟现在 CPU 差不多的也就几百块,没必要省那点钱买个电子垃圾。

写在后面

这套方案我用了一年多,基本上没啥问题。24 小时开机、低功耗、子网设备无感知,爽到。

另外,不要怪我写得这么笼统,毕竟每个学校的校园网都不太一样,很难写出一篇普适性的教程。这篇文章充其量算个 PoC,证明一下只要能折腾,还是能捣鼓出舒适的宿舍网络环境的。

如果你是大佬,甚至可以写个软件实现一样的功能,隐藏网卡、软件 NAT 啥的。不过我是菜鸡,也不想在这上面花太多心思,所以就这样吧。又不是不能用.jpg

至于这么折腾值不值得,那就见仁见智了。至少我是愿意的:你不让我开热点我就不开,那我岂不是很没有面子。老子又不是没交钱,凭什么?

smiling-dog

最后,祝各位早日摆脱傻逼校园网。

How to VLAN

介绍VLAN的基本概念和几种场景下的应用,而OpenWrt下VLAN处理机制和一般交换机有些不同,这里做了一个对比并给出了一种两台路由器之间的单线复用的方案

问题

计算机网络的教材对VLAN一笔带过,作业的却要用到交换机互联,之前看的VLAN的文章貌似都对应不到OpenWrt上去,也就很难有实践的机会;下面根据个人在宿舍组网上遇到的问题,一步步来探究VLAN的用法

后面又看到了N1盒子基于VLAN的单臂路由,又做了一些补充

多线接入

宿舍是上床下桌,每一张桌子下面有一个百兆的网口,通过负载均衡,很早就可以把网速跑到100Mbps了,这显然不够啊,因为宿舍WiFi是共用的,自然而然想到连接相邻的两个床位的网口,这样就有300Mbps了,这也是多线拨号的第一步

上图就是将LAN3与LAN4作双线接入,通过VLAN分别对应到eth0.3和eth0.4

此时LAN4与WAN是“直通”的,效果上来说,就是LAN4也可以插网线用电脑拨号了,如果是要给路由器做双线接入的话,则需要添加VLAN,再把一个LAN口添加到新VLAN中,最后建立接口拨号即可

交换

然而舍友还是需要网口拨号的,所以如果需要长期占用的话偶尔肯定是不太方便的,所以需要交换机来扩展一下网口,这一步已经可以通过简单的修改下OpenWrt路由器的Switch来实现,將LAN4和WAN划到同一个VLAN,两个接口就相当于在同一交换机下:

单线复用

然而,仅仅通过untagged只能实现多条线路的“汇聚”,能够达到100Mbps+的只有一台路由器而已,并没有实现“互通”,即每一台路由器都可以上到100Mbps+;不仅如此,还要实现相邻床位的路由器之间只用一根线连接就可以达到同样的网速,更具体的就是在一根网线传输不同的来源(网口)的数据

而VLAN的一个重要的功能恰好就是实现交换机之间的互通

单臂路由

这个需求源于有一台N1,之前看过VLAN的接入网络的方法,觉得网络结构更清晰,以此可以解决主路由算力不足的问题,但之前一直没有刷上OpenWrt,刷完之后发现居然没有交换机的Switch选项,赶紧翻出了之前看到的帖子:N1做主路由,新3做AP的最正统vlan连法教程,想起之前文档刚好有部分没看懂,刚好可以补充上

概念

首先还是OpenWrt的文档:VLAN,很早就读过,但是因为缺少具体的有解释的例子,当时没弄清楚VLAN tagged的机制

所以这里先结合华为的文档了解下基础的概念

VLAN Tag

首先需要理解VLAN标签是被添加到以太帧内部的一个4个字节的片段,其中VID也就是常说的VLAN ID

在一个VLAN交换网络中,以太网帧主要有以下两种形式:

  • 有标记帧(Tagged帧):加入了4字节VLAN标签的帧
  • 无标记帧(Untagged帧):原始的、未加入4字节VLAN标签的帧

常用设备中:

  • 用户主机、服务器、Hub只能收发Untagged帧(Linux系统可以通过安装软件实现收发Tagged帧)
  • 交换机、路由器和AC既能收发Tagged帧,也能收发Untagged帧
  • 语音终端、AP等设备可以同时收发一个Tagged帧和一个Untagged帧

VID & PVID

VID也就是数据帧中的12bit的VLAN ID,表示该数据帧所属VLAN的编号,而PVID(Port Default VLAN ID)又称为缺省VLAN,可以用于和VID做比较来判断Tag的情况

应用

最主要的应用是划分广播域,这部分可以参考图文并茂VLAN详解,然而和本文的关系不是很大

为了提高处理效率,设备内部处理的数据帧一律都是Tagged帧,例如在交换机内部的,在数据帧进入交换机的时候可能会按照一定的规则被打上VLAN Tag以方便下一步的处理,OpenWrt的Old Wiki的一张图很好地体现了这一点:

以太帧进入端口后被打上VLAN Tag,之后在传输的CPU的线路内(Port5-CPU),就同时传输带两种VLAN Tag的包

另外在交换机之间,可以在一条链路上使用两个VLAN也叫做Ethernet trunking,也有人称作单线复用,常见的应用:

  • 单臂路由(只有一个网口的路由器)
  • 使用一根网线同时传输IPTV和宽带的数据

交换机

这里参考的是上面的华为的交换机的文档,不同交换机可能有些不一样

Incoming & Outgoing

以收发的设备作为主体,指的是数据帧到达接口而没有完全进出交换机内部,举个例子:

  • 数据帧到达某一个接口时,路由器会对数据帧的VLAN情况做判断
  • 如果符合通过的规则,则放行做后续处理,不符合则丢弃
  • 后续处理可能就是剥离或者打上标签

链路类型和接口类型

配置VLAN:为了适应不同的连接和组网,设备定义了Access接口、Trunk接口和Hybrid接口3种接口类型,以及接入链路(Access Link)和干道链路(Trunk Link)两种链路类型,如下图所示

根据接口连接对象以及对收发数据帧处理的不同,以太网接口分为:

  • Access接口

Access接口一般用于和不能识别Tag的用户终端相连,只能收发Untagged帧,且只能为Untagged帧添加唯一VLAN的Tag

  • Trunk接口

Trunk接口一般用于连接交换机、路由器、AP以及可同时收发Tagged帧和Untagged帧的语音终端。它可以允许多个VLAN的帧带Tag通过,但只允许一个VLAN的帧从该类接口上发出时不带Tag(即剥除Tag)

  • Hybrid接口

Hybrid接口可以允许多个VLAN的帧带Tag通过,且允许从该类接口发出的帧根据需要配置某些VLAN的帧带Tag(即不剥除Tag)、某些VLAN的帧不带Tag(即剥除Tag)

Hybrid接口和Trunk接口在很多应用场景下可以通用,但在某些应用场景下,必须使用Hybrid接口。比如一个接口连接不同VLAN网段的场景(如图所示的Router连接Hub的接口)中,因为一个接口需要给多个Untagged报文添加Tag,所以必须使用Hybrid接口。

  • 接入链路只可以承载1个VLAN的数据帧,用于连接设备和用户终端
  • 干道链路可以承载多个不同VLAN的数据帧,用于设备间互连

处理机制

OpenWrt对VLAN Tag的处理机制见后文引用文档的加粗部分,此处暂作为理解的参考

  • Access端口

  • Trunk端口

  • Hybird端口

OpenWrt VLAN

OpenWrt的文档没怎么提及接口类型的概念,OpenWrt对VLAN设置的组织形式和普通的交换机有所不同,从机制介绍来看是比较接近Trunk端口的:发出的数据帧只有一个VLAN的数据帧不带Tag

OpenWrt文档所提到的:An untagged port can have only 1 VLAN ID 反映在:OpenWrt中的Switch设置VLAN时单个untagged Port无法再再其他VLAN上为Untagged,否则回提示:LAN 1 is untagged in multiple VLANs!

故抛开之前的端口类型,遵守VLAN的规则,兼容且实用就行

另外,不是所有OpenWrt设备都有Switch这个LuCI的配置选项,比如N1就没有,但是照样可以配置VLAN,位置在Interface的接口物理配置部分,由于无法像Switch那样有Tag之类的选项,

Tag机制

官方文档对Tag机制的介绍如下(散落在两处):

  • Tagged on “CPU (eth0)” means that the two VLAN ID tags used in this example (1, 2) are sent to the router CPU “as tagged data”. Remember: you can only send Tagged data to VLAN-aware devices configured to deal with it properly.
  • Untagged means that on these ports the switch will accept only the incoming traffic without any VLAN IDs (i.e. normal ethernet traffic). The switch will remove VLAN IDs on outgoing data in such ports. Each port can only be assigned as “untagged” to exactly one VLAN ID.
  • Off: no traffic to or from the tagged ports of this VLAN ID will reach these ports.

Ports can be tagged or untagged:

  • The tagged port (t is appended to the port number) is the one that forces usage of VLAN tags, i.e. when the packet is outgoing, the VLAN ID tag with vlan value is added to the packet, and when the packet is incoming, the VLAN ID tag has to be present and match the configured vlan value(s).
  • The untagged port is removing the VLAN ID tag when leaving the port – this is used for communication with ordinary devices that does not have any clue about VLANs. When the untagged packet arrives to the port, the default port VLAN ID (called pvid) is assigned to the packet automatically. The pvid value can be selected by the switch_port section.

特别指出,但是一般也用不上,在LuCI界面上看不到的PVID设置,设置具体在uci network switch_port部分:

Port PVID; the VLAN tag to assign to untagged ingress packets

无Switch配置

官方文档的位置在 Creating driver-level VLANs 一节,配置方式是通过在接口设置,选择自定义接口,在名称在做文章:如在物理网卡eth1上,通过自定义eth1.2接口的方式建立一个VLAN ID为2的接口,在使用Switch设置VLAN,如添加VLAN ID为3的VLAN之后,接口处也会出现eth0.3,逻辑上还是统一的;下面来看下文档对处理机制的描述:

If the incoming packet arrives to the interface with software VLANs (incoming packet to eth1) and has a VLAN ID tag set, it appears on the respective software-VLAN-interface instead (VLAN ID 2 tag arrives on eth1.2) – if it exists in the configuration! Otherwise the packet is dropped. Non-tagged packets are deliveded to non-VLAN interface (eth1) as usual.

即处理流入的包:接口只接收有相应Tag的包,相当于Switch中的VLAN在该接口设置为Tag

这样一来,一个物理网口可以同时收发带Untagged帧和Tagged帧,故使用VLAN来实现单臂路由也就很好理解了,配置的方式也不唯一

解决方案

回到本文开头提到的问题,仿照上面的Switch内部VLAN机制的图的形式,画了一张两台OpenWrt路由器通过VLAN互通,进而实现让两台路由器可以得到宿舍三个网口合计300Mbps的接入

需要说明的是:

  • 因为所有的VLAN都需要为拨号服务,所以这里略去了VLAN到CPU的一段
  • 格式为了照顾LuCI的设置界面显示,可能看起来有些不寻常
  • VLAN ID的外层意义就是接入的网口的标识,中间的TRUNK链路如何并不重要
  • 对WAN Interface的命名就相对随意了,例如Router 1的WAN_1应该命名为WAN_21更合适一点

最后的在宿舍的书桌背后的路由器如图

路由负载均衡:ECMP

介绍了Linux系统中等效多径路由(ECMP)及其在网络负载均衡上的应用,给出了OpenWrt下的启用的方法

参考

因为偶然发现了Linux内核中的ECMP这种负载均衡的方法,然后查了些资料,这里整理下(业余水平);文末留下了当时发现ECMP的记录

ECMP在工程方面用的很多,能找到的多是说明文档,介绍特性和成套的解决方案,但是基础的材料并不是那么好找,个人也是刚刚接触到ECMP,水平有限,这里先给出本文的主要参考文献

关于负载均衡,[译] 现代网络负载均衡与代理导论(2017)有一个较为全面的介绍,其中作者提到

关于现代网络负载均衡和代理的入门级教学材料非常稀少(dearth)。我问自己:为什么会这样呢?负载均衡是构建可靠的分布式系统最核心的概念之一。因此网上一定有高质量的相关材料?我做了大量搜索,结果发现信息确实相当稀少。 Wikipedia 上面负载均衡 和代理服务器 词条只介绍了一些概念,但并没有深入 、这些主题,尤其是和当代的微服务架构相关的部分。Google 搜索负载均衡看到的大部分都 是厂商页面,堆砌大量热门的技术词汇,而无实质细节。本文将给读者一个关于现代负载均衡和代理的中等程度介绍,希望以此弥补这一领域的信息缺失。

对此个人在经历一番搜索之后也是感同身受,所以才有了总结的想法;如果觉得上文过于“导论”(和本文的关系不大),华为的文档更贴近本文的主题一些,尽量看英文:Introduction to Load Balancing

Jakub Sitnicki’s Blog的系列博文:对Linux内核中的ECMP的实现深入浅出地做了介绍,如果感兴趣的话可以看看

最后是一篇相对详尽的中文资料,重点是ECMP在内核中的变更历史:ECMP在Linux内核的实现

原理及概念

ECMP也就是下面的路由表的情形,就是到某一个目的地址可以有多个下一跳路径可选

root@K2P:~# ip r
default metric 1
        nexthop via 10.170.72.254 dev pppoe-VWAN21 weight 1
        nexthop via 10.170.72.254 dev pppoe-VWAN22 weight 1
        nexthop via 10.170.72.254 dev pppoe-VWAN31 weight 1
        nexthop via 10.170.72.254 dev pppoe-VWAN32 weight 1
root@K2P:~# ip -6 r default
default metric 1
        nexthop via fe80::96db:daff:fe3e:8fcf dev pppoe-VWAN21 weight 1
        nexthop via fe80::96db:daff:fe3e:8fcf dev pppoe-VWAN22 weight 1
        nexthop via fe80::96db:daff:fe3e:8fcf dev pppoe-VWAN31 weight 1
        nexthop via fe80::96db:daff:fe3e:8fcf dev pppoe-VWAN32 weight 1 pref medium

看起来很简单,要弄清楚这个具体能做到什么程度就需要了解下具体的实现,这里一步一步来看

Packet/Flow

Packet对应的是IP分组(数据报、数据包),是数据在L3上传输的单元

对路由器而言,流(Flow)是共享某些特性的packet序列,比如同一个请求(连接)的packets有相同的路由路径

根据负载均衡的对象分:有Per-Packet和Per-Flow两种方式,文档中的两张图对此有个直观的对比

自然而然的会想到L4 Per-Packet负载均衡:每一个的Flow的Packets会被分流,可以实现多拨对看直播都可以加速的效果,然而本文并不会涉及:

Existing Multipath Routing implementation in Linux is designed to distribute flows of packets over multiple paths, not individual packets. Selecting route in a per-packet manner does not play well with TCP, IP fragments, or Path MTU Discovery.

故默认下文都是Per-Flow负载均衡,这就需要利用Packet的header fields信息把一个个的Packet和Flow联系起来,再进行下一跳的路由选择:

  • IPv4 L3 hash

     { Source Address, Destination Address }
    
  • IPv4 L4 hash

    { Source Address, Destination Address, Protocol, Source Port, Destination Port }
    
  • IPv6 L3 hash

    { Source Address, Destination Address, Flow Label, Next Header (protocol) }
    

    IPv6分组因为有Flow Label的存在,IPv6即使只用到L3 Hash也可以实现L4负载均衡

IPv6 Flowlabel IPv6数据报(packet)中有一个20字节的字段:流标号(流标签);进而可以用流标号取代路由表来处理流的路由,加速路由器对分组的处理;在ECMP中却提供了Flow的信息,故IPv6 ECMP是比较容易做的

L3/L4

更关键的还是负载均衡的层级,比如在多拨的情况下使用策略路由也可以做“负载均衡”,下面的命令往往提高BT的速度,这属于L3 Per-Flow负载均衡(左图):只在IP地址层级分流

ip rule add table 916
ip route add 10.173.0.0/16 via 10.170.72.254 dev pppoe-VWAN31 table 916
ip route add 10.170.0.0/16 via 10.170.72.254 dev pppoe-VWAN32 table 916

类似的方法对HTTP多线程下载并没有加速作用,对连接分流,需要L4负载均衡:多线程下载的请求之间source port不同,故L4 hash值基本不同,故会被分到不同的路径上,这样一来L4负载均衡是面向连接的就很好理解了,而内核在IPv4/IPv6上实现到一步有一段很长的历史:

Linux内核中ECMP

Linux内核的Git Commit,对发展历程感兴趣的还可以参考博文Celebrating ECMP in Linux,其中还讨论了设备的出站流量和转发流量的ECMP效果的不同,这里把ECMP的变更历史整理到一张表格中,以及对应时间的OpenWrt的内核版本信息:

Linux Kernel OpenWrt 内核版本 ECMP变更 ECMP形式
1997 | 2.1.68   IPv4 ECMP 加入内核 L3 Per-packet + route cache -> L3 Per-flow
2007 | 2.6.23   IPv4 multipath cached 移除 L3 Per-packet + route cache -> L3 Per-flow
2012.9 | 3.6   IPv4 route cache 被移除 L3 Per-packet -> L3 Per-packet
2012.10 | 3.8   IPv6 ECMP 加入内核 IPv6 Flowlabel -> IPv6 L4 Per-flow
2015.9 | 4.4 15.05 | 3.18 IPv4 ECMP:使用L3 Hash L3 Per-packet + L3 hash -> L3 Per-flow
2016.4 | 4.7   IPv4 ECMP: 增加邻居健康检查  
2017.2 17.01 | 4.4    
2017.3 | 4.12   IPv4 ECMP: 增加 L4 Hash L3 Per-packet + L3/L4 hash -> L3/L4 Per-flow
2017.11 | 4.14   IPv6 ECMP: ICMPv6 修复  
2018.1 | 4.16   IPv6 ECMP: 支持指定权重  
2018.4 | 4.17   IPv6 ECMP: 增加 L4 Hash  
2018.7 18.06 | 4.9/4.14    
2018.10 | 4.19      
2019.11 19.07 | 4.14.151    

这里可以推出(实际早期版本我也没有测试过),在默认的编译选项和内核版本下,较为实用的L4负载均衡,IPv4需要在18.06及之后的版本

IPv6由于使用了Flowlabel作为Hash的对象,根据表格,OpenWrt在15.05之后的版本就可以启用L4负载均衡

本文考虑更多的还是OpenWrt中的应用,更多信息参考本博客中的Speed_Up

启用ECMP

准备部分是从排查问题的角度来看的

在启用之前可以确认下编译内核时的下面选项,即IP: equal cost multipath,ECMP支持,较新版本的OpenWrt默认是打开的

  • CONFIG_IP_ROUTE_MULTIPATH=y

暂时不清楚使用下面的多个nexthop命令添加ECMP路由的依赖,只知道命令ip route的源于iproute2,如果出现如下报错:

Error: either “to” is a duplicate, or “nexthop” is a garbage.

可以尝试:

  • 安装ip-full再尝试,OpenWrt默认是ip-tiny,某些情况下也能使用多个nexthop命令添加ECMP路由
  • 使用route命令多次添加静态路由,可以启用IPv6的ECMP(详见文末的后记),实测在原版的OpenWrt可行
    route -A inet6 add 2000::/3 gw fe80::96db:daff:fe3e:8fcf dev pppoe-VWAN2
    route -A inet6 add 2000::/3 gw fe80::96db:daff:fe3e:8fcf dev pppoe-VWAN3
    

添加ECMP路由

这里直接引用iproute2的user Guide的Multipath routing部分:

ip route add ${addresss}/${mask} nexthop via ${gateway 1} weight ${number} nexthop via ${gateway 2} weight ${number}

Multipath routes make the system balance packets across several links according to the weight (higher weight is preferred, so gateway/interface with weight of 2 will get roughly two times more traffic than another one with weight of 1). You can have as many gateways as you want and mix gateway and interface routes, like:

ip route add default nexthop via 192.168.1.1 weight 1 nexthop dev ppp0 weight 10

Warning: the downside of this type of balancing is that packets are not guaranteed to be sent back through the same link they came in. This is called “asymmetric routing”. For routers that simply forward packets and don’t do any local traffic processing such as NAT, this is usually normal, and in some cases even unavoidable.

If your system does anything but forwarding packets between interfaces, this may cause problems with incoming connections and some measures should be taken to prevent it.

可以补充的是如果用的多个等带宽的PPPoE Interface的话,可以使用多个nexthop dev ${pppoe-dev}

修改内核运行参数

仅仅是上一步的话,可以见到在使用P2P下载时已经有负载均衡了,但是对HTTP的多线程下载并没有加速效果,因为一些Linux内核对IPv4的ECMP默认设置到L3 Hash,而且也没有开启邻居健康检查,所以需要修改下内核的运行参数,相关的具体的参数说明如下:

fib_multipath_hash_policy - INTEGER Controls which hash policy to use for multipath routes. Only valid for kernels built with CONFIG_IP_ROUTE_MULTIPATH enabled. Default: 0 (Layer 3) Possible values: 0 - Layer 3 1 - Layer 4 2 - Layer 3 or inner Layer 3 if present

fib_multipath_use_neigh - BOOLEAN Use status of existing neighbor entry when determining nexthop for multipath routes. If disabled, neighbor information is not used and packets could be directed to a failed nexthop. Only valid for kernels built with CONFIG_IP_ROUTE_MULTIPATH enabled. Default: 0 (disabled) Possible values: 0 - disabled 1 - enabled

echo "net.ipv4.fib_multipath_hash_policy=1" >> /etc/sysctl.conf
echo "net.ipv4.fib_multipath_use_neigh=1" >> /etc/sysctl.conf
sysctl -p

其他相关的内核运行参数(IPv6 Flowlabel等)可以参考ip-sysctl.txt

OpenWrt上启用ECMP

熟练的话完全根据上面的方法做了,以下是在校园网PPPoE接入下实践的,如果PPPoE拨号多播数量较多可以参考如何提高网速

准备

  • 在启用之前可以确认下编译内核时的选项CONFIG_IP_ROUTE_MULTIPATH=y(OpenWrt 18.06之后的版本默认已经开启)
  • IPv6 ECMP只在IPv6 NAT下测试过,受限于当前OpenWrt正式版的内核版本,未对内核参数做进一步测试
  • 加速的前提是下多拨可以加速(ISP限制)

添加虚拟网卡

OpenWrt安装kmod-macvlan后就可以添加虚拟网卡到不同的VLAN上

opkg update && opkg install macvlan

路由器上的RJ45网口是绑定到VLAN上的,如果是添加虚拟网卡到一个VLAN上就是单线多拨,添加到多个VLAN上就可以做多线多拨了

这里的eth0.2对应于WAN口(在Interface -> Switch可以看到WAN绑定在VLAN 2上),不同的设备可能有些许不同,这里在eth0.2上添加两个虚拟网卡

for i in  `seq 1 2`
do
  ip link add link eth0.2 name veth$i type macvlan
done

拨号

还是用脚本省事,填上用户名和密码即可,拨数为2,填下账号密码

#!/bin/sh
username=
password=
for i in  `seq 1 2`
do
  uci set network.VWAN$i=interface
  uci set network.VWAN$i.proto='pppoe'
  uci set network.VWAN$i.username="$username"
  uci set network.VWAN$i.password="$password"
  uci set network.VWAN$i.metric="$((i+1))"  
  uci set network.VWAN$i.ifname="veth$i"
  uci set network.VWAN$i.ipv6='1'
done
uci commit network

添加所有PPPoE接口到wan zone(担心影响到其他的网络环境的话手动也可以)

for i in `uci show network | grep pppoe | awk -F. '{print $2}'`
do
  uci add_list firewall.@zone[2].network=$i
done
uci commit firewall

添加ECMP路由

只用nexthop dev ${pppoe-dev}:

#IPv4
ip route replace default metric 1 nexthop dev  pppoe-VWAN1 nexthop dev  pppoe-VWAN2
#IPv6
ip -6 route replace default metric 1 nexthop dev  pppoe-VWAN1 nexthop dev pppoe-VWAN2

做完这一步就可以使用ip rip -6 r命令检查下路由表

修改内核运行参数

echo "net.ipv4.fib_multipath_hash_policy=1" >> /etc/sysctl.conf
echo "net.ipv4.fib_multipath_use_neigh=1" >> /etc/sysctl.conf
sysctl -p

测试

通过东北大学IPv6测速以及IPv4测速测试负载均衡的速度叠加效果,或者使用iftop命令查看各个接口上路由的实时速率

传入连接的问题

添加ECMP路由之后传入连接偶尔连的上,偶尔连不上,但是PT的上传之类的貌似又没有问题(可能因为上传也可以是主动发出的连接),如果有这方面需求的话需要添加策略路由,为某一接口上的地址指定路由规则,下面是IPv4的,完成之后可以从外部访问之类的,但是对其他的影响就不太清楚了,IPv6部分暂时没有测试条件…

ip rule add perf 20 from IP table 20
ip route add default table 20 dev INTERFACE

此处参考自Linux 平台上之 Multipath Routing 應用,非常难得的详细的文章,还是2001年的

后记:偶然发现的ECMP

这里保留当时的发现过程:(当时发现了这个功能非常开心,现在来看部分内容不准确,但是文末的脚本的效果要好于ECMP默认的方法)

只在K2P OpenWrt 18.06上面实践过,对LEDE 17.01无效

下面是在操作一番之后的路由表,对IPv6的测速显示网速翻了四倍

root@OpenWrt:~# ip -6 route | grep pppoe
default from 2001:250:1006:dff0::/64 via fe80::96db:daff:fe3e:8fcf dev pppoe-VWAN4 proto static metric 512 pref medium
2000:::/3 dev pppoe-VWAN4 proto static metric 256 pref medium
        nexthop via fe80::96db:daff:fe3e:8fcf dev pppoe-wan weight 1
        nexthop via fe80::96db:daff:fe3e:8fcf dev pppoe-VWAN2 weight 1
        nexthop via fe80::96db:daff:fe3e:8fcf dev pppoe-VWAN3 weight 1
        nexthop via fe80::96db:daff:fe3e:8fcf dev pppoe-VWAN4 weight 1

大致可以看出这已经是做了负载均衡,需要的只是安装好luci-app-mwan3,简单操作一下路由表,这里的网关地址和dev需要看具体情况

2000::/3 就是IPv6的单播(Unicast)地址了,在不做任何操纵的情况下,无PD的路由表(单拨)

default from 2001:250:1006:dff0::/64 via fe80::96db:daff:fe3e:8fcf dev pppoe-VWAN3 proto static metric 512 pref medium
2001:250:1006:dff0::/64 dev pppoe-VWAN3 proto static metric 256 pref medium
...

之后通过下面两条常规的添加路由表条目的命令:

route -A inet6 add 2000::/3 gw fe80::96db:daff:fe3e:8fcf dev pppoe-VWAN2
route -A inet6 add 2000::/3 gw fe80::96db:daff:fe3e:8fcf dev pppoe-VWAN3

发现路由表就出现了nexthup和负载均衡中的weight标记

root@OpenWrt:~# ip -6 route | grep pppoe
default from 2001:250:1006:dff0::/64 via fe80::96db:daff:fe3e:8fcf dev pppoe-VWAN3 proto static metric 512 pref medium
2000::/3 dev pppoe-VWAN3 proto static metric 256 pref medium
        nexthop via fe80::96db:daff:fe3e:8fcf dev pppoe-VWAN2 weight 1
        nexthop via fe80::96db:daff:fe3e:8fcf dev pppoe-VWAN3 weight 1
...

类似的网关添加过程对IPv4效果并不好,这里稍后再细说

之后还需要修改一下防火墙,这里用的还是NAT6中的那条命令

因为对路由表的修改在路由器重启之后会重置,所以还是要添加到开机的启动脚本或者添加到自定的防火墙规则之中,如果已经在NAT6配置过程中配置好了的话这一步就可以忽略了

ip6tables -t nat -I POSTROUTING -s `uci get network.globals.ula_prefix` -j MASQUERADE

实测的峰值速度可以到达双网口的满速,但是一样的问题,在UT,IDM,Thunder这种多线程下载软件下轻松满速,而在YouTube视频应用下,只有半速(甚至包括用IDM下载的情况下)

目前最新版本的mwan3也开始支持IPv6多拨了,但是个人还是觉得日常使用的话用以上的方法更加快捷,不过需要对网络有一定的了解,下面是一段针对IPv6 NAT的多拨hotplug脚本,用了一些OpenWrt开发时推荐的写法,比较实验性

#!/bin/sh
[ "$ACTION" = ifup ] || exit 0
ifaces=$(ubus call network.interface dump | jsonfilter -e '$.interface[@.proto="dhcpv6" && @.up=true].interface')
for iface_6 in $ifaces
do
  [ "$INTERFACE" = $iface_6 ]  || continue
  devices=$(ubus call network.interface dump | jsonfilter -e '$.interface[@.proto="dhcpv6" && @.up=true].device')
  ipv6_gw=$(ifstatus $iface_6 | jsonfilter -e '$.route[1].nexthop')
  for ipv6_dev in $devices
  do
    status=$(route -A inet6 add 2000::/3 gw $ipv6_gw dev $ipv6_dev 2>&1)
    logger -t NAT6 "Gateway: $ipv6_dev: Done $status"
  done
  exit 0
done

关于PT站的零零碎碎

遇到的问题,读过的文章,一点总结,希望能节约些时间的同时把事情做好

前言

初次接触到PT的概念是在初中,EACDY论坛的站长在115网盘链接失效后毅然决定要开办PT站,但是因为那是家里的带宽极为有限,没能提供多少的上传量;之后偶然在东南大学的虎踞龙盘PT见识到了教育网PT的繁荣,于是定了一个之后要去一所有PT的大学的目标,最后如愿以偿,却发现IPv6才是打通教育网和公网PT的关键;之后又是一次偶然的机会,接触到了PT站的一些技巧后…决定把本文放到博客上(仅涉及国内的PT站)

个人的PT站账号不多,数据仅仅是咸鱼水平,对公网PT知之甚少,内容多是引用以及摸索的经验,仅供参考

引用与推荐

文章

rhilip对国内的PT站数据有一个详细的统计分析,可以作为发展PT的参考:

PT实用工具&脚本分享:感谢给我发过邀请的yezi1000,顺着简介找到了博客,下面这篇文章介绍了搭建PT盒子的一些经验(和普通的娱乐用户关系不大)

torrentinvites.org:据说是一个卖PT邀请码的网站,该网页有PT站的数据统计及站点的分析,可以为进入某个公网PT提供了部分参考

ipv6 NAT后配置端口转发:使用IPv6 NAT的可以看下,说不定可以改善连接性,进而大大提高上传速度

这里还有一个用得上但是有些古老的软件,v6speed,类似于某种P2P点播软件:使用种子利用P2P传输就可以观看电影,一时半会还真的没找到同类型的软件,据说有解码能力有限的问题,最后一次更新在2015年

工具

PT站最关注的点:保种以及搜索下载

reseed:方便的跨站辅种工具,进到新的PT站,一个个搜索辅种往往需要花掉相当多的时间,这个几分钟就解决了,天津大学的同学开发的,注册账号需要北洋的Passkey,国内的部分站点可用

PT-Plugin-Plus:支持Chrome和Firefox的插件,提供站点数据概览,搜索聚合以及辅助下载功能;向往PT的一大原因就是简单且高质量,这个插件对此贡献也很大,比如在网页上看到有人推荐某个纪录片,右键搜索,下载一气呵成

如果要发电影(转种可能也用得上),PT Gen可以帮助生成信息

遇到的问题

PT的生存性

如果网络通畅的话下载热门的种子即可,但是如果上传速度很糟心的话,还是选择大量的保种路线,使用保种得到的积分换上传量比较好,所以打听好PT站点的生存策略和弄清楚自身的网络状况是很关键的

资源的发布时间

首先要搞清楚0day资源的概念,自行搜索,这里说下蓝光电影的发布时间的一个参考:blu-ray.com中的电影详情页面中可以看到蓝光碟片的发布时间,一般PT站可以提前一点点发出资源,不同的站点的一个区别就在于首发的速度,但顶级站点往往转种都是很快的

至于更普遍的WEB版或者TV版资源,看首播的时间就好,可以留意的是:

  • 有WEB录制组的站点,可以查看历史资源确定是否有录制计划
  • 电影录制比较特殊的地方在于版权,有些站点可能不让发
  • Auto Seed的存在,主要是对欧美剧集,可以第一时间转种,具体那些站点有可以参考Pt-Board

特别一点的是动漫,动漫资源的发布往往依赖于字幕组,就我所在的大部分PT站动漫更新都不是很及时,BT站 动漫花园,部分动漫字幕组出资源会第一时间放出来

代理与盒子

因为学校往往带宽比较贵,学生购置大容量硬盘也不太划算(刷数据和看电影是两回事),随意挂代理和购置盒子可以提高速度和节约流量,需要注意的事部分站点是限制这种方式的,尤其是刚进入站点的时候,如果一不小心被识别为盒子(挂代理的VPS供应商有时候会被识别),可能上去下载免费资源就会出现分享率爆炸的情况,所以此处需格外谨慎(尤其是路由器上挂透明代理)

NAS

因为电脑上没有安装3.5寸盘的空间,在经历过路由器挂BT的初等玩法后,还是组建了一台NAS用于个人的数据存储和下载管理

下载软件

NAS自带的下载软件源于Transmission:

  • 有配套的APP:DS Get,但是不太好用…
  • 支持订阅,规则也比较好写
  • 结合上Download Station Extension可以在Chrome,safari,Opera浏览器中使用右键直接下载,缺点是最多只能显示100个种子
  • 缺点之一就是默认是强制校验资源的完整性的,以至于添加资源特别麻烦
  • 缺点之二,种子太多容易卡顿

于是就转而使用了Docker的linuxserver\qBittorrent

  • 终于可以跳过校验了,结合之前的reseed工具,可以迅速添加几百个种子
  • 开源软件,自带开源的气质,各种选项,信息都会呈现出来
  • 需要结合后面的FlexGet实现订阅
  • 轻量化的Web界面反而成为了远程跨平台访问的优势

默认设置需要修改的主要是下载任务数量和连接数

IPv6问题

docker如果使用桥接网络是默认不支持IPv6的,个人安装网上的修改参数之类的方法最终也失败了,最后还是使用了hosts网络多尝试了几次成功了

订阅

比如说在0day资源出来之前可以先写好订阅,待到资源出种就可以第一时间自动下载好,查看下载列表就可以得知已经出种而不需要再去反复的检索

RSS

一般的NexusPHP架构的PT站都在搜索栏的右侧有个订阅的icon,设置好筛选就可以通过RSS获取种子的信息进而实现自动的下载

FlexGet

主要是弥补自带RSS的设置自由度不足以及给Docker的qBittorrent提供自动下载支持,为了省事,采用了Docker:wiserain-flexget,挂载一个qbittorrent可以访问的文件夹作为qbittorrent的种子监测文件夹,运行后就可以从网页打开FlexGet的界面,填写config即可

网络

若是用户之前都是公网IP且防火墙规则开放的情况就不多说了,主要是做种的时候看到有人在下载而本地的种子又没有上传就很折磨

传入连接

Tracker是PT用户都可以访问,用于上传BT客户端的IP及端口信息以方便用户之间的相互连接,试想一下这样的一个过程,当一个客户端A,得知客户端B正在做种,于是A直接向B发起了一个连接请求,也就是对B而言,该连接是一个传入连接,然而残酷的现实是:

  • 防火墙默认阻止了传入连接,在以校园网的IPv6防火墙和设备的默认防火墙策略为代表
  • 路由器的NAT类型默认阻止了传入连接

阻止传入连接不会影响正常的上网,因为日常的上网连接都是由内网的设备发起或是请求,好比开门发快递和收快递,而PT的传入连接呢?就好比一个陌生的快递突然送了过来,现实中可能是“来者不拒”,但是网络的世界往往要危险的多

至于防火墙这一级,如果可以管理的话,开放UT的监听端口即可,如果不行的话可以尝试设置uPnP做自动端口转发

PT站上显示的“可连接”仅仅是可以连接到Tracker服务器,实际的效果可以靠UT、qbittorrent的用户标识(Flag)判断

Flag所代表的意义:

D = 当前正在下载 (感兴趣且没有被阻塞)
d = 本级客户端需要下载, 但是对方没有发送 (感兴趣但是被阻塞)
U = 当前正在上传 (感兴趣且没有被阻塞)
u = 对方需要本机客户端进行上传, 但是本机客户端没有发送 (感兴趣但是被阻塞)
O = 开放式未阻塞
P = 使用μTP协议连接,兼具TCP的可靠性及UDP的连接性
S = 对方被置于等待状态
I = 对方为一个连入连接
K = 对方没有阻塞本机客户端, 但是本机客户端不感兴趣
? = 本机客户端没有阻塞对方, 但是对方不敢兴趣
X = 对方位于通过来源交换获取到的用户列表中 (PEX)
H = 对方已被通过 DHT 获取.
E = 对方使用了协议加密功能 (所有流量)
e = 对方使用了协议加密功能 (握手时)
L = 对方为本地/内网用户 (通过网络广播发现或位于同一网段中)

NAT类型

NAT类型概述以及提升NAT类型的方法对NAT类型做了简要的介绍

NAT对PT的影响是很大的,如基于OpenWrt的Linux路由使用netfilter的MASQUERADE实现的NAT的默认类型是Symmetric NAT,或者称为NAT4,是对传入连接最不友好的一种NAT,IPv4的解决办法:

Chion82/netfilter-full-cone-nat写了从DNAT到netfilter内核子系统,浅谈Linux的Full Cone NAT实现,而LGA1150为OpenWrt做了Netfilter and iptables extension

然而,教育网主要还是IPv6,IPv6的Full Cone NAT还没见过,暂时只有ipv6 NAT后配置端口转发

从WiFi速率到无线通信

各种WiFi的速率是怎么来的?WiFi的速度靠什么提高?如何理解和应用相关理论来改善网络质量?业余理解

缘起于Win10显示的图书馆的WiFi信息

1568137490504

5GHz,165信道,WiFi 4???这个是什么情况呢,是不是有哪里显示错了?然后就是速率最高只有144MHz,这个速率又是怎么来的?

从网络协商速率开始

tnext wifi linkspeed

这里以802.11AC 1T1R MCS9 HT80 带宽Short GI为例计算网络连接速率,由上面的公式以及下面的引用可以知道:

\[Rate HT80 = (234MHz* 8bit *5/6 )/(3.2us + 0.4us)= 433.33Mbps\]

这个也就是最常见的单天线的5G WiFi速率,大概的解释如下

80MHz中一个符号有234个数据子载波,使用256QAM时每个子载波每次传输8bits数据,编码率为5/6,而传输时间等于符号持续时间加上保护间隔

802.11ax子载波带宽

从OpenWrt主页的Associated Stations右侧的字段的含义又是什么呢?

650.0 Mbit/s, 80MHz, VHT-MCS 7, VHT-NSS 2, Short GI
650.0 Mbit/s, 80MHz, VHT-MCS 7, VHT-NSS 2, Short GI

我按照个人理解的通信流程整理下,水平有限…

通信部分的概念

把速率计算公式根据后面的原理部分化简一下: \(\begin{align}Rate & =(N_{sub}\times log(N_{QAM}) \times R_{coding})/(N_{sub}/N_{HT}+GI) \\& =\frac{log(N_{QAM}) \times R_{coding}}{1/N_{HT}+GI/N_{sub}}\end{align} \\\) 其中$N_{sub}$为子载波数,$N_{HT}$为频宽

提高网络速率的方法可以粗略的归结到各个子项上面

物理层

频段与频宽

WiFi所用的频段主要是三个,下图也列出了不同的频宽下选择某个信道对频段的占用情况

802.11n: 2.4G频段

img

每相邻的2个信道之间的频宽就是5Mhz,最大频宽为40MHz,对于国内的2.4G只有1-13信道可以用,用1信道,频宽为20Mhz,则信道2,3,4,5都被占用了;如果是40Mhz,侧信道2,3,4,5,6,7,8,9也被占用了,当然只在传输数据时才会占用的。这就为什么在家附近因有大量wifi造成网络堵塞缓慢的原因了。

802.11ac: 5G频段

1568145613985

中国WIFI设备在5GHz下可以使用的信道有36,40, 44, 48, 52, 56, 60, 64, 149,153, 157, 161, 165。而每个信道频宽为20Mhz,如果信道为149,当要用80Mhz时,则153,157,161都要被占用了

802.11ad: 60G频段,近距离高速无线传输专用,现在基本上见不到了

802.11ax: WiFi 6的频段依然是之前的2.4G和5G频段,主要是把最大频宽定在了160MHz

比较有趣的是某个WiFi对频宽的占用越大,有效的传输距离越短,对环境的干扰越小,最后又作用与可以占用更大的频宽来做近距离的高速传输,故各种规格的WiFi是可以和谐共处的

MIMO技术

通过多条通道来发送数据,常用 nTnR,或者 n x n 来表示,比如说2T2R也就是2x2 MIMO,以及OpenWrt上用的NSS:Number of spatial streams后接数字表示空间流的数目

看起来是最简单粗暴的提高无线速率的方式,然而实际上会遇到多径效应导致高误码率,最终还是采取了一系列的措施来尽量克服多径效应

FEC:QAM

FEC (Forward Error Correction):按照无线通信的基本原理,为了使信息适合在无线信道这样不可靠的媒介中传递,发射端将把信息进行编码并携带冗余信息,以提高系统的纠错能力,使接收端能够恢复原始信息。

正交幅度调制QAMQuadrature Amplitude Modulation)是一种在两个正交载波上进行幅度调制调制方式。这两个载波通常是相位差为90(π/2)的正弦波,因此被称作正交载波,这种调制方式因此而得名

802.11n所采用的QAM-64的编码机制可以将编码率(有效信息和整个编码的比率)从3/4 提高到5/6。所以,对于一条空间流,在MIMO-OFDM基础之上,物理速率从58.5提高到了65Mbps(即58.5乘5/6除以3/4)

QAM编码是用星座图(点阵图)来做数据的调制解调,实际应用中是2的N次方的关系。比如说16-QAM ,16是2的4次方,一次就可以传输4个bit的数据;802.11n是64-QAM ,是2的6次方,因此在64个点阵的一个星座集合里面,用任意一个点可以携带六个bit的数据信息

到了802.11ac,就变成了256-QAM,是2的8次方,802.11ac相对于802.11n在编码上面的速率提升了33%。802.11ax之后引入了更高阶的编码,就是2的10次方,1024-QAM

我们都知道从8到10的提升是25%,也就是相对于802.11ac来说,802.11ax的性能又提高了25%,变成了1024-QAM,一个符号可以携带10个bit的数据

img

MIMO-OFDM

在室内等典型应用环境下,由于多径效应的影响,信号在接收侧很容易发生(ISI),从而导致高误码率。OFDM调制技术是将一个物理信道划分为多个子载体(sub-carrier),将高速率的数据流调制成多个较低速率的子数据流,通过这些子载体进行通讯,从而减少ISI机会,提高物理层吞吐。

用于Wi-Fi通信的有OFDM和OFDMA技术:802.11a/g/n/ac无线电当前使用正交频分复用(OFDM)用于802.11频率上的单用户传输,将比特串流对应到QAM调制的符号

子载波的分类

OFDM有三种类型的子载波,如下所示:

数据子载波:这些子载波将使用与802.11ac相同的调制和编码方案(MCS)以及两个新的MCS,并添加1024-QAM

导频子载波:导频子载波不携带调制数据;它们用于接收器和发射器之间的同步

未使用的子载波:剩余的未使用的子载波主要用作保护载波或空子载波以抵抗来自相邻信道或子信道的干扰

例如:20 MHz 802.11n/ac 信道由64个子载波组成——52个子载波用于承载调制数据; 4个子载波用作导频载波;8个子载波用作保护频带;每个OFDM子载波的宽度是20MHz/64=312.5KHz。

TNEXT 802.11 OFDM

不同频宽的数据子载波的数量(第三列)关系见下表

802.11ac 子载波数参数

OFDM符号持续时间

把每个子载波传输的内容是一个符号(比如QAM调制的结果),由于把一个载波分为了多个子载波并行处理,符号持续时间隔也就是处理单个子载波的时间, 为实现最大频谱效率,一般取符号持续时间=1/子载波间隔 ,对802.11 n/ac,符号持续时间为 3.2us=1/312.5

保护间隔

Short Guard Interval (GI),由于多径效应(即使单路传输也存在)的影响,信息符号(Information Symbol)将通过多条路径传递,可能会发生彼此碰撞,导致ISI干扰。为此,802.11a/g标准要求在发送信息符号时,必须保证在信息符号之间存在800 ns的时间间隔,这个间隔被称为Guard Interval (GI)。802.11n仍然使用缺省使用800 ns GI

当多径效应不是很严重时,用户可以将该间隔配置为400ns(=0.4us即Short GI),对于一条空间流,可以将吞吐提高近10%,即从65Mbps提高到72.2 Mbps。对于多径效应较明显的环境,不建议使用Short Guard Interval (Short GI)

预设的调制和编码方案

HT/VHT/HEW

分别对应802.11 n/ac/ax,指的是高、超高吞吐,高效无线网络(High-Efficiency Wireless - HEW),后接数字指示频宽

MCS

MCS (Modulation Coding Scheme)调制和编码方案

在802.11a/b/g时代,配置AP工作的速率非常简单,只要指定特定radio类型(802.11a/b/g)所使用的速率集,速率范围从1Mbps到54Mbps,一共有12种可能的物理速率。

到了802.11n时代,由于物理速率依赖于调制方法、编码率、空间流数量、是否40MHz绑定等多个因素。这些影响吞吐的因素组合在一起,将产生非常多的物理速率供选择使用。比如基于Short GI,40MHz绑定等技术,在4条空间流的条件下,物理速率可以达到600Mbps(即4*150)

为此,802.11n提出了MCS的概念。MCS可以理解为这些影响速率因素的完整组合,每种组合用整数来唯一标示,于是就有了下表

ieee-802-11n-ac-modulation-coding-schemes

至于802.11ax暂时作为上面的补充,添加了MCS10,11

TNEXT 802.11ax速率表

回到最开始的问题

把本文最开始的OpenWrt的截图中的VHT-MCS 9对应过来就可以很方便的查到是866.7Mbps的速率

对于斐讯K3的5G速率可以由 256-QAM 4ss 80MHz SGI来计算1024QAM的速率,即由8bit到10bit,增加25%的速率,大约2100Mbps

144Mbps的由来,可以在Spatial Streams = 2的几行中找到对应的HT20-MCS 15 SGI以及VHT20-MCS 7 SGI,也就是说两种都有可能,后面我还是拿专业点的软件测试了下,确实是5G的WiFi,参考下表就有该5G WiFi不符合WiFi 5的标准,降为WiFi 4情有可原,只是后面那个802.11n就有些尴尬了

1568200987531

学校的AP是双频的,因为AP数量比较多,组网的时候几乎全频段都有,所以每个频段的频宽都设置的比较低以避免互相干扰,144Mpbs的协商速率对单设备限制50Mbps的情况足够了

另外有了上面的一些基础概念之后,方便选择合适的路由器和网卡,尤其是在当前这个向WiFi 6 过渡的阶段

WiFi 6的新特性

img

▲802.11ax技术构成模块示意图

TP-LINK的官网已经有比较简洁美观的介绍了,本文就接着上文提到的部分加以延伸

MU-MIMO

MU-MIMO 即Multi-User Multiple-Input Multiple-Output 的缩写,直译为“多用户 多输入 多输出”, 是最新Wi-Fi技术标准802.11ac Wave 2(即802.11ac 2.0标准)的最重要特性之一

802.11ax设备借鉴了802.11ac的部署经验,将使用波束成形技术同步将数据包发送至不同空间的用户。 换言之,AP会计算每个用户的信道矩阵,并同时将波束导向不同的用户——每路波束包含针对其目标用户的特定数据包。 802.11ax一次可支持8个多用户MIMO传输包的发送,而802.11ac一次可支持4个MIMO数据包。 而且,每次MU-MIMO传输都可能有自己的调制和解码集(MCS)和不同数量的空间串流。 以此类推,当使用MU-MIMO空间复用时,接入点会与以太网交换机进行比较,将冲突域从大型计算机网络缩小至单个端口。

作为MU-MIMO上行方向的新增功能,AP将通过一个触发帧从每个STA发起上行同步传输。 当多个用户及其数据包同时响应时,AP将信道矩阵应用于所接收的波束并将每个上行波束包含的信息分开, 同时它还可能发起上行多用户传输,从而接收来自所有参与STA的波束形成反馈信息

img

至于MU-MIMO的实际情况可以参考有关的测试:ACWIFI

OFDMA

802.11ax无线电可以利用正交频分多址(OFDMA) ,其是OFDM数字调制技术的多用户版本。OFDMA将信道细分为较小的频率分配,称为资源单元(RU)。

OFDM和OFDMA都通过称为逆快速傅立叶变换(IFFT)的数学函数将信道划分为子载波。子载波的间隔是正交的,因此尽管它们之间缺少保护带,它们也不会相互干扰。

img

通过细分信道,可以同时发生小帧到多个用户的并行传输。每个资源单元内的数据和导频子载波在OFDMA信道内都是相邻且连续的

802.11 OFDMA

802.11ax引入了更长的12.8μs的OFDM符号时间,这是传统符号时间3.2μs的四倍。子载波间隔等于符号时间的倒数。由于符号时间较长,子载波大小和间隔从312.5KHz降低到78.125KHz。窄子载波间隔允许更好的均衡并因此增强信道鲁棒性。

上面提到的OFDMA规格对理论速率提升约为10%

MU-OFDMA

802.11ax标准借鉴4G蜂窝技术的技术进步,在相同信道带宽中服务更多用户的另一技术是: 正交频分多址(OFDMA)。 基于802.11ac已经使用的现有正交频分多路复用(OFDM)数字调制方案,802.11ax标准进一步将特定的子载波集分配给个体用户, 即,它将现有的802.11信道(20、40、80和160MHz频宽)分为带有预定义数量的副载波的更小子信道。 802.11ax标准还借用现代LTE术语,将最小子信道称为资源单元(RU),最少包含26个副载波。

密集用户环境下,许多用户通常无力争夺信道的使用机会,现在正交频分多址使用更小巧——但更具专用性的子信道同时服务多个用户,因此提升了每个用户的平均数据吞吐量。 802.11ax系统可能通过不同的资源单元规模实现信道的多路复用。注意,对于每20MHz带宽,信道的最小部分可容纳9个用户

img

imgimg

AP依据多个用户的通信需求决定如何分配信道,始终在下行方向分配所有可用的资源单元。 它可能一次将整个信道仅分配给一个用户——与802.11ac当前功能相同——或者它可能对其进行分区,以便同时服务多个用户。

img

BSS Color

BBS(Base Service Station) Color, 基于色码的空间复用,为了改善密集部署场景中的系统层级性能以及频谱资源的使用效率,802.11ax标准实现了空间重用技术。 STA可以识别来自重叠基本服务集(BSS)的信号,并根据这项信息来做出媒体竞争和干扰管理决策。

这部分和速率关系不大

信号质量与无线速率

信号的衡量标准

一般我们都会有个信号强弱的标准,比如常用的WiFi和Cellular的Icon上被填满的图标面积,然而打开一些调试工具看到的是dbm这个单位,例如在OpenWrt的Wireless详情中有: Tx-Power: 23 dBm Signal: -64 dBm | Noise: 0 dBm Tx-Power指的是路由器信号的发射功率,无线功率一般以mw为单位,但是因为WiFi信号的能量通常为mw级,因此业界将WIFI信号大小表示为与1mw的强度比,用dbm来表示,对应关系是 \(signal=10log(\frac{P}{1mw})\) 这就有个非常方便的计算方式:

降低3dBm,是指信号强度降低到原先的1/2(二分之一)。

降低10dBm,是指信号强度降低到原先的1/10(十分之一)。

降低30dBm,是指信号强度降低到原先的1/1000(千分之一)。

有了这个之后,可以对信号的强度做一个大致的判断: 下图来自RSSI等级和信号强度

使用上图来源的网站提供的软件可以绘制出一个大致的信号强度分布图,可以参考来的调整AP的位置

除了dbm表示无线的收发功率之外,还要考虑到信道中的信噪比(SNR),噪声也可以使用dbm为单位,所以计算dbm为SNR单位的时候把二者相减即可

与无线速率的关系

首先是会影响到协商速率,在发射端的信号到接收端,中间存在衰减和损失,其对通信的影响就是会产生高误码率,故为了达到可靠通信的需求需要采取高纠错性能的编码和调制方式,也就是影响到MCS,进而影响到协商速率和实际传输速率,而调整的标准就看设备的厂商的调教了

应用

有了上述的铺垫,就有了一些改善无线网络质量的途径,但是最重要的还是认清现实,理性对待

频段

因为某一个频段内的信道容量有限,在拥挤的时候噪声也多,故在选择频段的时候,尽可能的避开当前区域拥挤的信道,可以使用路由器的无线桥接功能(wireless scan)工具,查看路由器附近的信道占用的情况,或者用Netspot工具检测当前区域网络情况

特别说明的是2.4G频段已经相当的拥挤了,对于有高可靠性网络环境要求的情况,建议还是网线或者使用5G频段

提高发射功率

这里可以说是个经验上的技巧,首先,路由器的发射功率是受到国家标准的严格限制的,但是对于某些可以切换无线地区的路由器来说,可以通过该途径来提高发射功率,或者使用某些频段进而提高发射功率

使用高增益的天线,使用内置信号放大器的AP也是同样的逻辑

增加AP

Mesh,信号放大器,主路由+AP,无线漫游都是类似的途径,高端的设备往往配备了更好的硬件和算法,这点也是毋庸置疑的

参考

802.11 WiFi协议浅析

802.11ax高效率无线标准介绍-National Instruments

第七代无线技术802.11ax详解

02.11ax 11ac 11n WiFi全速率表

简说各种wifi无线协议的传输速率

IEEE 802.11理论速率计算

❌