软路由是目前非常流行的家庭网络部署方案。软路由一般是指带至少两个有线网口的 X86 主机,但 ARM 架构的单网口电视盒子也可以是软路由,只要能够安装 Linux 并配置好路由功能即可。相较于成品路由器,软路由往往有更强的硬件与计算能力,也有更灵活的玩法。

唯一的不足是,软路由缺乏专门的无线芯片与功放电路,无线能力很弱。因此,软路由一般不会直接作为无线 AP,需要与成品路由相互配合:软路由负责处理路由相关功能,成品路由负责输出无线信号。这就是广泛使用的 AC + AP 方案。

我们这里讨论的是,如何在 AC + AP 方案中,实现类似成品路由的“访客网络”功能。

访客网络的功能定义

成品路由除了输出 WiFi 信号 SSID-Main,还可以选择性地输出 WiFi 信号 SSID-Guest。主人在不告诉客人 SSID-Main 密码的情况下,客人可以通过连接 SSID-Guest 来使用主人家的网络进行上网。

这个时候,客人从 SSID-Guest 中可能会获取到不同网段的 IP 地址,也可能会获取到与主人网络相同网段的 IP 地址,但无论哪种,关键是客人是被隔离在主人网络之外的,因此主人网络中所有的设备资源,客人都是无法访问的。

这个逻辑是非常正确且必要的。因为如果主人网络中有一台 Nas,他可能不希望客人能够访问到。当然,可以给 Nas 设置密码,但这相比于直接的网络隔离,安全性会更差。

AP 访客网络的问题

作为成品路由,虽然被当作 AP 使用,但也还是有访客网络功能的。

但是,在 AC + AP 方案中,AP 的访客网络功能其实是个摆设,因为它现在只负责接入,无法做到网络隔离。不管从 SSID-Main 还是 SSID-Guest 接入,都由软路由负责分配 IP 地址,而软路由是无法区别用户是从哪个 SSID 接入的,因此也无法做网络隔离。

曾经的解决方案

为了解决这个问题,曾经设计如下几种方案:

  1. 为软路由加上一张无线网卡,专门负责访客网络的接入。
  2. 使用 iptables 对 MAC 地址进行过滤,只允许白名单中的设备访问局域网中的其他设备。

在第一种方案中,使用 Linux 中 NetworkManager 自带的热点模式(而不是使用 hostpad),让无线网卡为客人提供 SSID-Guest 接入点,并分配与主网不同的网段,从而实现网络隔离。缺点是无线网卡的信号比成品路由信号弱,无法覆盖到全屋,这对客人来说用户体验是非常不好的。

在第二种方案中,iptables 的规则非常难写,并且需要在其规则中维护一堆 MAC 白名单地址。无论是在可配置性还是可维护性上都是非常差的。另外一个问题是,使用无线网络桥接连接过来的 IP 数据包,其 MAC 地址不是设备的地址,而是无线桥接路由器的 MAC 地址,因此也无法对设备进行准确的判断与过滤。

目前的解决方案

目前的解决方案如下

  • 使用成品路由作为 AP,同时提供 SSID-Main 与(可选的) SSID-Guest 接入点。
  • 在软路由上配置 DHCP 服务器,一般是 dnsmasq,在其配置文件中维护 MAC 白名单,为白名单中的设备分配主网段地址,为其他设备分配客人网段地址。
  • 在配置 dnsmasq 之前,需要为软路由的 LAN 口同时设置主客两个网段的地址。
  • 使用 iptables 禁止两个网段的互通。但也可以是禁止从客人网络到主人网络的通讯,允许从主人网络到客人网络的通讯。

这种解决方案的优点是部署简单、易维护,并且也能准确识别设备的 MAC 地址。

缺点也是有的。客人可以设置静态 IP 来进入主人网路。但通过为主人网络设置不常见的网段即可在一定程度上缓解这个问题。在只有主人知道主人网络网段的情况下,静态 IP 地址的设定也为需要临时进入主人网络、又不需要改动白名单的设备提供了方便。