我已经通过 设置了 Raspberry Pi Wi-Fi 热点hostapd
,dnsmasq
并iptables
使用这个优秀的教程进行路由:https://thepi.io/how-to-use-your-raspberry-pi-as-a-wireless-access-point/。虽然我跳过了第 8 步,但一切都运行正常,我每天都在使用它,已经 2 年了。在我的环境中,wlan0(集成 Wi-Fi 芯片)被禁用,wlan1(外部 Wi-Fi)被启用。
最近我注意到一些计算机有令人讨厌的流量(包括 NetBIOS),我想只阻止这些流量。但是,这对我来说非常重要:我还希望客户端能够相互通信。不幸的是,我尝试了很多次,都没有成功。
以下是我尝试过的:
- 使用过滤
iptables
-> 恼人的数据包被看到并被阻止,但仍被 WLAN 上的任何计算机接收iptables -t raw -I PREROUTING -p tcp --dport 137 -j DROP
iptables -t raw -I PREROUTING -p udp --dport 137 -j DROP
iptables -t raw -I PREROUTING -p tcp --dport 138 -j DROP
iptables -t raw -I PREROUTING -p udp --dport 138 -j DROP
iptables -t raw -I PREROUTING -p tcp --dport 139 -j DROP
iptables -t raw -I PREROUTING -p udp --dport 139 -j DROP
- 使用过滤
ebtables
-> 恼人的数据包被看到并被阻止,但仍被 WLAN 上的任何计算机接收ebtables -I INPUT -i wlan1 -p ip --ip-protocol udp --ip-destination-port 137 -j DROP
ebtables -I INPUT -i wlan1 -p ip --ip-protocol udp --ip-destination-port 138 -j DROP
ebtables -I INPUT -i wlan1 -p ip --ip-protocol udp --ip-destination-port 139 -j DROP
ebtables -I FORWARD -i wlan1 -p ip --ip-protocol udp --ip-destination-port 137 -j DROP
ebtables -I FORWARD -i wlan1 -p ip --ip-protocol udp --ip-destination-port 138 -j DROP
ebtables -I FORWARD -i wlan1 -p ip --ip-protocol udp --ip-destination-port 139 -j DROP
ebtables -I OUTPUT -o wlan1 -p ip --ip-protocol udp --ip-destination-port 137 -j DROP
ebtables -I OUTPUT -o wlan1 -p ip --ip-protocol udp --ip-destination-port 138 -j DROP
ebtables -I OUTPUT -o wlan1 -p ip --ip-protocol udp --ip-destination-port 139 -j DROP
- 使用设置进行过滤
ap_isolate=1
-hostapd.conf
> 烦人的数据包被阻止,但客户端无法相互通信 - 使用设置进行过滤
ap_isolate=1
并hostapd.conf
添加iptables rules
-> 客户端无法相互通信iptables -t filter -A FORWARD -i wlan1 -o wlan1 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -t filter -A FORWARD -i wlan1 -o wlan1 -j ACCEPT
iptables -L -n -v --line-number
当我从测试机器发送 UDP 广播帧时,计数器会很好地递增。 的原理相同。ebtables
这让我相信我的规则很好。
我目前的结论是:iptables
(OSI 级别 3)和ebtables
(OSI 级别 2)看到并阻止了流量,但没有在正确的级别采取行动,因为似乎hostapd
(OSI 级别 1)已经将网络数据包广播到了 WLAN 上的客户端。
下面是我的测试配置的一个小图:
- RaspberryPi 具有 iptables + ebtables 设置并通过 实时显示计数器
watch -n 1
。 - 设备 1 在 Wi-Fi 子网(/24 网络,因此目标 IP 为 xyz255)上以广播方式将 UDP 帧发送到端口 138
- 设备 2 使用 Wireshark 嗅探网络并看到这些 UDP 帧到达
+-----------------+
| Device 1 |
((| 172.18.0.240/24 |
+-----------------+
-----------+ +-----------------+
INTERNET |--------| 192.168.0.243 |
-----------+ | RaspberryPi |
| 172.18.0.1/24 |))
+-----------------+
+-----------------+
((| Device 2 |
| 172.18.0.235/24 |
+-----------------+
我希望我已经足够准确地描述了我的情况。如果不准确,请向我询问更多详细信息。
因此,我的问题是:“我怎样才能阻止 UDP 数据包向端口 137、138、139 广播,但仍然允许同一 WLAN 上的客户端相互通信以进行其他所有操作?”
非常感谢您的帮助。
答案1
无线 AP 正在处理 LAN:它在第 2 层工作。我将简化并认为无线帧就像以太网帧(在考虑接入点时这几乎是正确的,即使事实并非如此):802.11 帧头中的四个第 2 层地址)。
此设置ap_isolate=1
可防止在 AP 驱动程序的低层桥接帧。相反,这些帧现在被发送到网络堆栈。此堆栈在第 2 层没有太多工作要做(没有桥接),并将以 IP 数据包(以及 ARP 数据包、IPv6 数据包等)的形式传输要发送给主机的帧,由第 3 层的路由堆栈处理。
一旦到达第 3 层路由,数据包就可以使用主机的 INPUT 规则进行过滤,或者在路由时到其他 IP LAN使用 FORWARD 规则。
但在所有情况下,不打算发送给主机的帧都会被丢弃,而不会发送给其他 STA:STA 之间无法通信,这是 的作用之一,ap_isolate=1
并且无法被过滤iptables(错误的层)也不ebtables(无可用桥)。
为了能够处理和过滤帧ebtables(以太网桥帧表管理)需要一个桥接器,即使这个桥接器的唯一成员是单个无线网卡WLAN1。
以下是执行此操作的步骤。这些步骤并不完整。它们必须集成到操作系统的配置中才能正确启动设置,并且必须调整一些内容,主要是因为 IP 设置已从WLAN1接口br0接口(例如:DCHP服务器接口,其他iptables规则等)。
创建一座桥梁(您必须将其集成到操作系统设置中):
ip link add br0 up type bridge
将 IPv4 配置从
wlan1
移至br0
(ditto integration/boot)。wlan1
不得接收任何 IPv4 地址:172.18.0.1/24 现在应该是仅有的在br0
。 (WLAN1也不应该再参与 IPv6 的使用:)sysctl -w net.ipv6.conf.wlan1.disable_ipv6=1
。无线连接将中断,直到hostapd已重新启动。ip address flush dev wlan1 ip address add 172.18.0.1/24 dev br0
wlan1
调整任何与现在引用相关的配置br0
(例如:DHCP 服务器的接口(如果明确定义的话),也许还有一些iptables规则)。在 中
/etc/hostapd/hostapd.conf
,除了 和 之外ap_isolate=1
还interface=wlan1
添加:bridge=br0
并重新启动hostapd。您现在应该得到类似这样的结果:
# bridge link show dev wlan1 3: wlan1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master br0 state forwarding priority 32 cost 100
使能够发夹形在WLAN1桥接端口来撤消的效果
ap_isolate=1
。这是处理OP问题的这一部分所必需的:但客户端无法相互通信
使用以下命令:
bridge link set dev wlan1 hairpin on
在WLAN1桥接端口现在将被回显到同一个桥接端口。这里桥接端口和相关媒体是WLAN1界面及其无线电波。
客户端通信现已恢复。无需像以前那样执行:
STA1 --> AP --> STA2
它现在正在做:
STA1 --> AP --> (wlan1)--br0--(wlan1) --> AP --> STA2
现在可以添加桥接层适当的防火墙规则。
如果系统上有多个桥接器,还应使用--logical-in
/ --logical-out
,否则就不需要了。同样,我没有在下面包含-i wlan1
/ ,-o wlan1
因此它可以在任何桥接器端口上运行(因此包括 的单个桥接器端口wlan1
)br0
。选择您喜欢的。
阻止端口 137 的示例:每行分别阻止从 STA 到 AP(还包括阻止路由到eth0)、从 STA 到 STA 以及从 AP 到 STA(也包括从eth0案件)。
ebtables -A INPUT --logical-in br0 -p ip --ip-protocol udp --ip-destination-port 137 -j DROP
ebtables -A FORWARD --logical-in br0 -p ip --ip-protocol udp --ip-destination-port 137 -j DROP
ebtables -A OUTPUT --logical-out br0 -p ip --ip-protocol udp --ip-destination-port 137 -j DROP
要仅阻止端口 137 的广播而不阻止单播(如标题所示),可以使用以下规则。 可能有多种方法可以做到这一点(这里我利用了这样一个事实:在 LAN 中携带 IPv4 目标广播地址的帧具有以太网目标广播地址 (ff:ff:ff:ff:ff:ff))。 仅显示 FORWARD 情况:
ebtables -A FORWARD --logical-in br0 -d Broadcast -p ip --ip-protocol udp --ip-destination-port 137 -j DROP
笔记:
通过加载内核模块br_netfilter也可以
net.bridge.bridge-nf-call-iptables=1
使用iptables(甚至nftables)代替或补充ebtables过滤框架IPv4 类型(临时转换为 IPv4数据包为了...的利益iptables)遍历桥接路径(在 IPv4 路由路径之前和之后)。描述如下:基于 Linux 的桥接器上的 ebtables/iptables 交互。这可能会让那些还没有准备好处理由此引起的细微破损的人感到非常困惑,所以我不建议使用它。nftables还可以处理过滤,而且最近的版本有更好的功能(例如从内核 5.3 开始它变成了原生的连接跟踪支持桥接路径,无需依赖br_netfilter)。