Apache HTTPD中使用Require forward-dns实现IPv6子网访问控制的方法咨询
你遇到的这个痛点我太懂了——用DNS集中管理上百个虚拟主机的IP白名单,那种随时增删IP不用改配置的爽感,换成IPv6后肯定不想丢对吧?
可惜的是,Require forward-dns本身确实只支持严格匹配完整的IPv4/IPv6地址,没办法直接识别子网段。不过我们可以通过几个变通方案来实现类似效果,既保留DNS管理的灵活性,又支持IPv6子网:
方案一:用DNS TXT记录存子网,结合Apache表达式判断
把原来的A/AAAA记录换成TXT记录,在authorized-ips.mydomain.tld下存所有允许的IPv6子网(比如2001:db8:2:1::/64)和IPv4地址/子网。然后用Apache的Require expr来解析这个TXT记录,再校验客户端IP是否在范围内。
示例配置如下:<RequireAll> Require expr %{REMOTE_ADDR} -ipmatch gethostbyname("authorized-ips.mydomain.tld", "TXT") </RequireAll>注意:这个方法需要Apache 2.4.10及以上版本,因为
gethostbyname和-ipmatch是较新版本才支持的表达式特性。管理的时候直接修改DNS的TXT记录就行,和原来的方式一样方便。方案二:mod_rewrite配合DNS做预验证
用mod_rewrite先获取DNS里的允许子网列表,匹配客户端IP后设置一个环境变量,再通过Require env来控制访问。比如:RewriteEngine On # 用RewriteMap从DNS对应的文本源获取允许的子网 RewriteMap allowed_subnets txt:https://authorized-ips.mydomain.tld/allowed_subnets.txt # 检查客户端IP是否匹配任意允许的子网 RewriteCond %{REMOTE_ADDR} ^${allowed_subnets:*} RewriteRule ^ - [E=ALLOWED_ACCESS:1] Require env ALLOWED_ACCESS这个方案需要你维护一个可通过域名访问的文本文件,里面每行一个子网/IP,DNS只需要指向这个文件的地址就行。虽然配置稍复杂,但扩展性很强,适合需要更复杂规则的场景。
方案三:第三方模块扩展forward-dns功能
如果你愿意折腾,可以找找有没有第三方Apache模块能扩展Require forward-dns的匹配逻辑,让它支持子网。不过这类模块通常比较小众,后续维护成本可能高一些,优先级可以放低。
至于你提到的Require ip,虽然直接,但确实丢了DNS集中管理的优势,所以上面的方案应该更贴合你的需求。个人建议先试试方案一,改动最小,最接近你原来的使用习惯。
备注:内容来源于stack exchange,提问作者Bil

