热点防火墙在租约之前就拦住了 DHCP
客户端子网规则永远匹配不上第一个 DHCP 请求,因为该请求来自 0.0.0.0。应改为放行本地路径。
新手机连上热点,却显示不出地址,也始终拿不到地址。接入点没问题,DHCP 守护进程在运行,你写的防火墙规则看起来也和地址规划一致。但它实际要求的是:客户端已经拥有它正在申请的地址。第一个 DHCP 报文根本没有地址,所以规则永远不会生效。
观察客户端接入
从客户端一侧跟踪一次关联。无线完成关联,客户端发出 DHCP 发现,服务器提供报价,客户端发出请求,服务器确认,直到这时客户端才拥有可用于其他用途的地址。
在这次最终确认之前,客户端无法使用网关承载普通流量。子网规则忘记的正是这个窗口。
第一个报文里究竟有什么
RFC 2131 规定,客户端在取得地址之前的 DHCP 广播使用全零源地址。客户端到服务器的报文发往 UDP 端口 67,服务器到客户端的报文发往 UDP 端口 68。因此发现报文以 0.0.0.0 作为源地址到达,而要求源地址位于客户端子网内的规则自然匹配不上。
这不是客户端配置错误。这是协议按设计工作,而且只可能发生在这一窗口内。
究竟由哪条路径处理
如果接入点自己发放租约,这就是本地服务对话;在按 IP 过滤的本地路径中,它涉及输入和输出策略。经 VPN 转发的客户端流量是另一个决定,而为该流量做 NAT 又是另一回事。把这三者混为一谈,正是让狭窄的例外变成宽泛放行的原因。
报文在哪里被处理,取决于守护进程和所用的防火墙体系。原始套接字实现、网桥布置以及更早的过滤钩子都可能把它移到或挡在完全不同的位置。添加规则之前,请确认守护进程的接口绑定和实际生效的钩子。
从论坛抄来的通用输入与输出配方,并不能证明你的实现会以同样的方式经过这些链。
回应并不总是广播
只放行广播回应的例外同样是错的。DHCP 回应的目的地址取决于客户端状态和报文字段,协议同时规定了广播和单播两种情形。如果你的服务器以单播回应它即将分配的地址,只放行广播的规则就会挡住收尾的那一步。规则要按已配置服务器实际执行的交互来写。
后续的租约续期会在另一种状态下重复这次交互,所以要为它们留出余地,而不只是为第一次接入。
先窄范围修复,再检查其余部分
保留现有策略,找到缺失的 DHCP 放行,并把范围限定在面向客户端的接口、协议和这两个端口上。先证明请求到达了服务,再证明服务作出了回应。这是两个不同的观察,而即使过滤完美,服务或地址池的配置仍可能出错。
清空表并不是 DHCP 的配置步骤。在 iptables 中,flush 会删除所选链或表中的规则,而清空 NAT 表并不会创建转换规则。设置宽泛的 ACCEPT 策略会移除与租约无关的防护,所以两者都不属于可复用的热点修复方案。
客户端拿到租约之后,把 DNS、转发和 VPN 出口当作独立任务分别检查。租约只建立本地地址,仅此而已。