shixudong@163.com
无线AP上大都有一个选项:启用AP隔离,启用该功能后,连接到同一AP的无线终端之间不能互相通信,但该功能并不限制无线终端和有线终端之间的通信。本人对Linux下用hostapd实现AP隔离进行了一些分析,特此记录。
Hostapd参数ap_isolate,用于控制AP隔离,但hostapd本身并不实现这一功能,只是将该参数通过nl80211传递给mac80211,由mac80211来实现AP隔离功能(鉴于mac80211与softmac驱动配套使用,fullmac驱动压根不需要使用mac80211,所以使用fullmac驱动的无线设备不保证支持AP隔离功能)。经对mac80211相关源码进行分析,ap_isolate的真实作用是控制无线AP收到包后,是通过调用dev_queue_xmit将包通过无线网卡直接发送出去(ap_isolate=0),或是通过调用netif_receive_skb交由本机上层网络栈处理(ap_isolate=1)。
ap_isolate=0时,无线终端之间数据包经由AP无线网卡直接通信(此时AP行为如同HUB),并不抵达AP上层网络栈。ap_isolate=1时,无线终端之间数据包只发往AP上层网络栈,如AP没加入网桥,其上层网络栈为无线AP三层,因数据包目标MAC不是AP无线网卡MAC(包类型对应PACKET_OTHERHOST),包将被三层DROP;如AP已启用网桥,其上层网络栈为网桥,无线终端之间数据包由网桥进行二层转发,但由于桥转发本身的内在机制,网桥收到的包不允许从同一端口再次转发出去,故包被二层DROP。故ap_isolate=1时,无论是否加入网桥,无线终端之间都无法通信,从而实现AP隔离。同一网桥下无线终端和有线终端之间不存在上述二层转发限制,可以互相访问。
在与网桥配合使用时,ap_isolate=1除了实现AP隔离外,还可利用multicast_snooping优化组播性能或利用SDN对无线终端进行管控,其实质都是将无线终端之间的数据包引导到AP的网桥处理。由此引发了一个新的挑战,既希望利用网桥处理数据包的优势,又需要关闭AP隔离功能,让无线终端之间互相通信,显然,此时无法通过改变ap_isolate来实现上述目的,为此可利用网桥端口hairpin模式控制AP是否隔离。设置网桥无线端口的hairpin_mode=1后,从同一无线端口进来的包允许通过hairpin功能原路返回,无线终端之间数据包可以进行二层转发,从而实现互相通信,这也是新版Openwrt实现无线AP的标准配置(ap_isolate=1、hairpin_mode=1)。
其实Linux是相当灵活的,可以用多种方式实现同一目的。当ap_isolate=1的主要目的是为了将无线终端之间数据包引导到AP的网桥处理时,还可通过网桥无线端口的isolated参数控制AP是否隔离(此时hairpin_mode应固定为1,否则AP隔离始终处于开启状态):isolated=1,开启AP隔离,isolated=0,关闭AP隔离。
上文分析了hostapd参数ap_isolate=1时网桥无线端口参数hairpin_mode、isolated如何控制无线终端之间的通信行为,这两个参数属于“或”关系,某种意义上是等效的。(1)hairpin_mode=0,始终开启AP隔离;hairpin_mode=1,通过isolated控制AP隔离开启与否。(2)isolated=1,始终开启AP隔离;isolated=0,通过hairpin_mode控制AP隔离开启与否。但如ap_isolate=0,鉴于无线终端之间相互通信不经过网桥,此时参数hairpin_mode、isolated压根无法影响或控制无线终端之间的通信,AP隔离始终处于关闭状态。
顺便提一下,isolated作为网桥参数,不仅可以控制AP隔离(前提是ap_isolate=1,数据包经由网桥处理),还可以控制同一网桥下无线终端和有线终端之间的相互通信:数据包进出端口的isolated均设为1,即可隔离两个端口上所连接设备之间相互通信。