隧道建立成功,登录成功,网络上的每台主机都能响应。这不是 VPN 坏了,而是 VPN 没有权限模型。RouterOS 认证账号之后,就把它的数据包当作任何人的数据包来路由,因此限制必须由防火墙提供。在不破坏登录的前提下加上这条限制,就是全部工作。

认证结束的地方,正是权限开始的地方

PPP 会话一旦建立,客户端的数据包就和任何其他接口的流量一样进入 forward 链。如果路由器的 forward 策略是宽松的,这名顾问在登录时就继承了这份宽松。账号从未携带任何范围,所以账号上没有可改的东西。规则集是给员工写的,新会话只是顺带加入了它。

在动手之前先确认请求走的是哪一条路径。 发往路由器后方主机的流量经过 forward,而发往路由器本身的流量(包括 winbox 和 SSH)经过 input。只覆盖 forward 的范围,会让设备对同一个客户端保持开放。

两条链都需要一个决定,即使决定是让 input 保持关闭。这个选择属于访问申请,而不是事后的想法。

把会话挂到一张命名列表上

PPP 配置文件可以在会话启动时,把分配给它的地址放进一张命名地址列表。这样临时的隧道地址就变成防火墙能按名字匹配的东西,会话结束时条目自动消失。账号于是从配置文件继承范围,而不是从一条把地址写死的规则继承。

先建配置文件,再把 secret 显式绑定上去。仍然指向默认配置文件的 secret,会重现原来的问题。

给配置文件和列表起能看出职责的名字,并用申请编号给两者加注释。一个配置文件可以服务多个范围相同的人,而列表仍然能标识每一个活动会话。这比按人写一条规则更容易复核。

/ppp profile add name=scoped-consultant remote-address=consultant-pool address-list=vpn-scoped-clients
/ppp secret add name=consultant password=... service=ovpn profile=scoped-consultant

把允许的服务记在一张列表里

把被允许的服务器放进它自己的地址列表,而不是把地址嵌进过滤规则。列表可以被审计、扩展和注释,服务器搬迁时消费它的规则不用改。只有一条记录时看起来多余,等第二台主机出现就不多余了,而它通常会出现。

地址动态或做负载均衡时匹配列表,地址固定且稳定时直接匹配地址。只要注释写清服务和负责人,两种选择都读得明白。

除了主机,也要限定协议和端口。对主机放行而不限端口,会打开该主机运行的每一项服务,比大多数访问申请的本意都宽。端口是权限的一部分,不是以后再补的细节。

/ip firewall address-list add list=vpn-targets address=10.0.0.10 comment="consultant RDP target"

把跳转排在所有宽泛放行之前

跳转规则把来自受限列表的转发流量送进一条私有链,整条策略只占三行。第一条规则放行允许的目标和端口,最后一条丢弃其余一切。跳转必须排在 forward 中任何宽泛放行之上,因为更早的放行意味着跳转永远不会执行。把 established 和 related 的放行放在跳转之前,回程流量才继续流通。

确认没有任何 fasttrack 规则能把这些流量带过受限链。fasttrack 会绕过剩余的过滤路径,而被 fasttrack 的受限会话根本算不上受限。

如果路由器自身的服务也应当不可达,就对 input 链重复同样的决定。挡住转发流量却让 winbox 敞开,只算做了一半。

/ip firewall filter
add chain=forward action=jump jump-target=scoped-vpn src-address-list=vpn-scoped-clients
add chain=scoped-vpn action=accept protocol=tcp dst-address-list=vpn-targets dst-port=3389
add chain=scoped-vpn action=drop

用计数器和列表成员关系来验证

从客户端测试被允许的服务和一项必须失败的服务,然后读取路由器上的规则统计。accept 和 drop 计数器显示每个包走了哪条路径,这是客户端看不到的。同时确认活动会话的地址出现在受限列表中。

列表为空,说明账号在另一个配置文件上,或者配置文件丢了地址列表设置。被允许的服务失败而 drop 计数器上涨,说明目标或端口与客户端发出的不一致。

在下结论之前,先用名字和地址各测一次同一个服务。名称解析失败,从客户端看和端口被封一模一样。然后把配置文件、两张列表和唯一允许的服务记进访问申请,下一次复核就是比对,而不是重建。

/ip firewall filter print stats where chain=scoped-vpn
/ip firewall address-list print where list=vpn-scoped-clients

相关文章