ROS标记域名并不是在防火墙规则里直接写域名,而是通过脚本把域名解析成IP并写入address-list,再对这个列表做mangle标记。这套思路绕开了RouterOS原生不支持域名匹配的限制,实际落地时用ROS7.1以上版本配合内置DNS缓存和脚本调度,可以做到秒级更新,且对转发性能几乎没有影响,下面直接给你一套能跑的配置逻辑,再拆开讲原理和排错。
ROS标记域名怎么做:配置步骤与命令详解
先认识ROS标记域名的真实机制
RouterOS的防火墙、路由表、mangle规则都只认IP地址,不认域名,所谓ros标记域名,本质是两条腿走路:第一步把域名解析结果收集到一个名为address-list的名单里,第二步在mangle里匹配这个名单的IP,再打上路由标记(routing mark),这个机制和OpenWrt里的ipset+nftables分流思路是一模一样的,只是ROS的脚本语法更老派,但稳定性在商用场景里更被认可。
要完成整套动作,你至少需要三个零件:
- RouterOS系统版本:推荐7.x以上,ROS7的容器和内置DNS转发能力比6.x强很多,处理域名列表更顺手。
- 一个可靠的解析通道:例如本地DNS缓存开启后,把需要标记的域名交给ROS自己的DNS解析器去查,解析成功的记录会自动出现在IP DNS的静态表里。
- 一段脚本:定期把域名对应的IP灌进address-list,并清理已经失效的条目。
准备一套可用的脚本模板
下面这段脚本是ROS官方社区里流传比较广的写法,用来把一段域名列表解析后写入address-list,名字叫DOMAIN_MARK,你可以把它粘贴到System > Scripts里新建一个脚本,再丢给Scheduler定时执行。
:local domainList "www.google.com
www.youtube.com
api.example.com"
:foreach domain in=$domainList do={
:local resolved [/ip dns resolve $domain];
:if ([:len $resolved] > 0) do={
:if ([/ip firewall address-list find where list="DOMAIN_MARK" address=$resolved] = "") do={
/ip firewall address-list add list="DOMAIN_MARK" address=$resolved comment="auto: $domain"
}
}
}
这段脚本会把每一个域名解析出来的IP单独添加为一条address-list记录,注意要点:
- 域名列表每行一个,不要用逗号或空格分隔。
-
解析失败的域名会自动跳过,不会卡住脚本。
- 重复添加时,先find判断再add,避免address-list膨胀。
把标记结果发布到路由表
名单有了,接下来就是mangle规则,假设你的外网口是pppoe-out1,内网是bridge-local,我们要求所有匹配到DOMAIN_MARK的流量走一个独立的路由表to_proxy:
- 在IP > Firewall > Mangle里新建一条规则,链选prerouting,Src Address填你的内网网段,例如192.168.1.0/24。
- 在Advanced选项卡里,Src Address List选
DOMAIN_MARK。 - 在Action选项卡里,Action选mark routing,New Routing Mark填
to_proxy,Pass Through不打勾。
然后去IP > Routes里添加一条静态路由,Gateway指向你的代理网关(比如旁路由的IP,通常是192.168.1.2),Routing Mark选to_proxy,这样,标记域名的IP一旦出现在名单里,流量就会自动走这条路由出国或走代理,其余流量照常走默认线路。
ROS域名分流实践:白名单直连与代理场景
ROS按域名标记路由的配置示例
有网友在实际配置中会把整个流程写成一条定时任务,TTL设为5分钟一次,下面是他分享的完整脚本骨架,你可以参考后按自己的域名列表调整,这个示例比前面的基础版本更实用,因为它加入了去重和TTL管理,防止address-list无限增长。
:local ttl 300s
:local domainList "www.google.com
www.youtube.com
api.telegram.org
raw.githubusercontent.com"
/ip firewall address-list remove [find where list="DOMAIN_MARK" comment~"auto:"]
:foreach domain in=$domainList do={
:local resolved [/ip dns resolve $domain];
:if ([:len $resolved] > 0) do={
/ip firewall address-list add list="DOMAIN_MARK" address=$resolved comment="auto: $domain" timeout=$ttl
}
}
这个版本的特点是先把旧的自动条目全删掉,再重新添加,结合timeout参数,既保证了名单新鲜度,又不会留下很久以前的IP残留,如果你用ROS7,还可以在IP > DNS里开启Allow Remote Requests,让ROS自己作为内网的DNS转发器,这样resolve命令的成功率会更高。
广告域名拦截的另一个用途
ros标记域名的玩法不只是分流,你可以把一批广告追踪域名放进另一个列表,比如AD_BLOCK,然后在mangle里对匹配这个列表的IP做drop或reject,实现内网级别的广告拦截,这个用法和DNS黑名单的思路不同,
它拦截的是IP本身,比单纯污染DNS更彻底,因为即使设备硬编码了DNS服务器也逃不掉,不过要注意,有些大型网站的CDN域名和广告域名共用IP,这种名单误杀率较高,只建议用来拦截那些独立IP的广告服务。
ROS标记域名后为什么没生效的排查方法
域名列表没更新的常见原因
- ROS内置DNS缓存是空白的,如果你的RouterOS没有开启DNS缓存,或者内网设备根本没有把DNS指向ROS,
/ip dns resolve $domain这个命令就查不到结果,address-list自然一直是空的,处理办法是:IP > DNS里勾选Allow Remote Requests,并且把DHCP服务器的DNS选项改为ROS的局域网IP。 - 脚本执行频率太低,域名解析结果是会变的,尤其CDN类域名,几分钟内IP就可能轮换,如果你把Scheduler设成一天一次,那白天很多时间段内名单都是滞后的,表现为分流时有时无。
- address-list里条目重复堆积,如果不做清理,旧IP和新IP会同时存在,整个列表体积变大后,mangle匹配性能会轻微下降,解决办法是定期执行
remove,或者利用timeout参数自动过期。
路由表不生效的处理思路
- 检查mangle的接口方向,多数情况下标记应在
prerouting链做,这时源IP是内网设备,目的IP是要被标记的域名IP,方向正确,如果你错放在output链,那只对路由器自身发起的流量生效,内网设备完全不受影响。 - 确认路由表条目存在且距离正常,IP > Routes里如果
to_proxy路由显示unreachable,说明Gateway(旁路由IP)在你当前网络里不可达,检查旁路由是否开机、网线是否连通。 - 检查防火墙过滤规则是否先于mangle丢弃了流量,ROS的filter规则是优先于mangle处理的,如果你的防火墙默认丢弃了来自某些IP段的转发包,那mangle根本见不到这些流量。
ROS域名分流和OpenWrt分流相比哪个更好用
两者实现机制的区别
OpenWrt上流行的分流方案是dnsmasq + ipset,或者直接上passwall、openclash这类插件,它们的核心优势是把域名筛选、规则更新、代理节点切换都做成了可视化界面,小白也能轻松上手,而ROS的强项不在界面,而在
脚本的可编程性和路由策略的精细度:
- 规则粒度:ROS可以在address-list的基础上叠加多级标记,比如把
DOMAIN_MARK再按端口、协议细分,生成完全独立的拓扑路径,这在OpenWrt里实现起来要麻烦很多。 - 系统稳定性:RouterOS在长时间高负载运行时表现更稳,内存占用低,很少出现dnsmasq进程崩溃的问题。
- 维护门槛:ROS需要手动维护脚本和域名列表,OpenWrt则有一键更新规则库的功能,行业共识认为,ROS适合有一定网络基础的玩家或需要稳定运行的小型办公网络,OpenWrt更适合追求便捷的家庭用户。
适合不同场景的选择建议
如果你之前一直在用OpenWrt且从未遇到问题,那没必要为了“ROS更专业”而迁移,但当你需要同时处理多线负载、策略路由、域名分流三件事,又希望尽量减少设备数量时,ROS一台设备能顶OpenWrt加交换机加额外路由器的组合。ROS标记域名的学习曲线确实陡,但跑通一次之后,后面几乎不用再折腾。
常见问题解答
ROS怎么按域名标记路由?
先通过脚本将域名解析结果写入address-list,再在IP > Firewall > Mangle中设置规则,Src Address List选择该address-list,Action选择mark routing并指定新的Routing Mark,最后在IP > Routes中添加一条指向代理网关的静态路由,Routing Mark选择刚才设置的标记。
RouterOS能把域名写入address-list吗?
可以,RouterOS 6.47及以上版本支持/ip firewall address-list add address=域名的语法,系统会自动在实际匹配时尝试解析域名,但在较老版本中,这种写法会直接报错或无法生效,更稳妥的做法是使用脚本先解析域名再添加IP,这种方式适用于所有版本,对于大名单(几百条以上),建议使用分页配合脚本批量处理,避免把RouterOS的命令行卡死。
为什么我的ROS域名分流总是不彻底?
多数情况下是因为DNS解析结果发生了变化,而脚本更新不及时,建议把定时任务间隔缩短到5分钟以内,同时开启ROS的DNS缓存和远程请求,并在脚本中清理旧的address-list条目,逐条排查就能解决问题。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/660432.html





