Filter

MikroTik RouterOS 中的防火墙 filter 通过预定义链(input、forward、output)允许或阻止流量,从而控制数据包流向,并可通过选项接受特定服务或丢弃恶意数据包。IPv4 通过 /ip/firewall/filter 配置,IPv6 通过 /ipv6/firewall/filter 配置,文档中还提供了保护路由器本身和 LAN 设备的示例。

Filter

防火墙 filter 用于允许或阻止转发到本地网络、源自路由器或发往路由器的特定数据包。

有两种设置过滤的方法:

  • 允许特定流量,丢弃其他所有流量。
  • 只丢弃恶意流量,允许其他所有流量。

两种方法各有利弊。例如,从安全角度看,第一种方法安全得多,但每当需要放行新服务的流量时,都需要管理员介入。该策略能很好地控制流量,并降低因服务配置错误而被攻破的可能性。

另一方面,在保护客户网络时,要放行用户可能使用的所有服务,对管理而言将是场噩梦。因此,在高级配置场景中,仔细规划防火墙至关重要。

防火墙 filter 由三个无法删除的预定义链组成:

  • input —— 用于处理通过某个接口进入路由器、且目的 IP 地址属于路由器自身地址之一的数据包。穿过路由器转发的数据包不会按 input 链的规则处理。
  • forward —— 用于处理穿过路由器的数据包。
  • output —— 用于处理源自路由器、并从某个接口离开路由器的数据包。穿过路由器转发的数据包不会按 output 链的规则处理。

IPv4 的防火墙 filter 配置可通过 /ip/firewall/filter 菜单访问,IPv6 则通过 /ipv6/firewall/filter 菜单访问。

防火墙示例

让我们看一个基本的防火墙示例,它同时针对 IPv4 和 IPv6 协议,用于保护路由器本身以及路由器后面的客户端。

IPv4 防火墙

保护路由器本身

设置防火墙时遵循的经验法则:

  • 针对 new 连接进行处理,以降低路由器负载。
  • 接受你需要的内容。
  • drop 其他所有内容;可以设置 log=yes 来记录部分攻击者,但请记住,在遭受猛烈攻击时这会增加 CPU 负载。

我们始终从接受已知且已放行的连接开始,因此第一条规则应当是接受 "established" 和 "related" 连接。

/ip/firewall/filter
add action=accept chain=input comment="default configuration" connection-state=established,related

现在我们可以继续接受一些新连接。在本例中,我们希望允许从任意地址访问 ICMP 协议,而其他所有内容仅允许来自 192.168.88.2-192.168.88.254 地址范围。为此,我们创建一个地址列表和两条防火墙规则。

/ip/firewall/address-list
add address=192.168.88.2-192.168.88.254 list=allowed_to_router
/ip/firewall/filter
add action=accept chain=input src-address-list=allowed_to_router
add action=accept chain=input protocol=icmp

最后,我们丢弃其他所有内容:

add action=drop chain=input

刚创建的完整规则集合:

/ip/firewall/filter
add action=accept chain=input comment="default configuration" connection-state=established,related
add action=accept chain=input src-address-list=allowed_to_router
add action=accept chain=input protocol=icmp
add action=drop chain=input
/ip/firewall/address-list
add address=192.168.88.2-192.168.88.254 list=allowed_to_router

保护 LAN 设备

保护用户的概念非常相似,区别在于此处我们阻止不想要的流量,并接受其他所有流量。

首先,我们将创建一个名为 "not_in_internet" 的 address-list,供防火墙 filter 规则使用:

/ip/firewall/address-list
add address=0.0.0.0/8 comment=RFC6890 list=not_in_internet
add address=172.16.0.0/12 comment=RFC6890 list=not_in_internet
add address=192.168.0.0/16 comment=RFC6890 list=not_in_internet
add address=10.0.0.0/8 comment=RFC6890 list=not_in_internet
add address=169.254.0.0/16 comment=RFC6890 list=not_in_internet
add address=127.0.0.0/8 comment=RFC6890 list=not_in_internet
add address=224.0.0.0/4 comment=Multicast list=not_in_internet
add address=198.18.0.0/15 comment=RFC6890 list=not_in_internet
add address=192.0.0.0/24 comment=RFC6890 list=not_in_internet
add address=192.0.2.0/24 comment=RFC6890 list=not_in_internet
add address=198.51.100.0/24 comment=RFC6890 list=not_in_internet
add address=203.0.113.0/24 comment=RFC6890 list=not_in_internet
add address=100.64.0.0/10 comment=RFC6890 list=not_in_internet
add address=240.0.0.0/4 comment=RFC6890 list=not_in_internet

防火墙 filter 规则简要说明:

  • 具有 connection-state=established,related 的数据包会被加入 FastTrack 以获得更快的数据吞吐,防火墙将只处理 new 连接。
  • 丢弃 invalid 连接,并以前缀 "invalid" 记录日志。
  • 丢弃从本地网络尝试访问非公网地址的行为,前面应用了 address-list=not_in_internet,"bridge" 是本地网络接口,对尝试以前缀 "!public_from_LAN" 记录日志。
  • 丢弃未经过 NAT 的入站数据包,ether1 是公网接口,对尝试以前缀 "!NAT" 记录日志。
  • 跳转到 ICMP 链以丢弃不想要的 ICMP 消息。
  • 丢弃来自互联网且源地址不是公网 IP 的入站数据包,ether1 是公网接口,对尝试以前缀 "!public" 记录日志。
  • 丢弃来自 LAN 但源地址不属于 LAN IP 的数据包,192.168.88.0/24 是本地网络子网。
/ip/firewall/filter
add action=fasttrack-connection chain=forward comment=FastTrack connection-state=established,related
add action=accept chain=forward comment="Established, Related" connection-state=established,related
add action=drop chain=forward comment="Drop invalid" connection-state=invalid log=yes log-prefix=invalid
add action=drop chain=forward comment="Drop tries to reach not public addresses from LAN" dst-address-list=not_in_internet in-interface=bridge log=yes log-prefix=!public_from_LAN out-interface=!bridge
add action=drop chain=forward comment="Drop incoming packets that are not NAT`ted" connection-nat-state=!dstnat connection-state=new in-interface=ether1 log=yes log-prefix=!NAT
add action=jump chain=forward protocol=icmp jump-target=icmp comment="jump to ICMP filters"
add action=drop chain=forward comment="Drop incoming from internet which is not public IP" in-interface=ether1 log=yes log-prefix=!public src-address-list=not_in_internet
add action=drop chain=forward comment="Drop packets from LAN that do not have LAN IP" in-interface=bridge log=yes log-prefix=LAN_!LAN src-address=!192.168.88.0/24

在 "icmp" 链中只允许需要的 ICMP 代码:

/ip/firewall/filter
  add chain=icmp protocol=icmp icmp-options=0:0 action=accept \
    comment="echo reply"
  add chain=icmp protocol=icmp icmp-options=3:0 action=accept \
    comment="net unreachable"
  add chain=icmp protocol=icmp icmp-options=3:1 action=accept \
    comment="host unreachable"
  add chain=icmp protocol=icmp icmp-options=3:4 action=accept \
    comment="host unreachable fragmentation required"
  add chain=icmp protocol=icmp icmp-options=8:0 action=accept \
    comment="allow echo request"
  add chain=icmp protocol=icmp icmp-options=11:0 action=accept \
    comment="allow time exceed"
  add chain=icmp protocol=icmp icmp-options=12:0 action=accept \
    comment="allow parameter bad"
  add chain=icmp action=drop comment="deny all other types"

IPv6 防火墙

保护路由器本身

与 IPv4 配置非常相似,区别在于我们必须处理 IPv6 正常工作所需的更多协议。

首先,我们创建一个 address-list,用它来允许访问设备:

/ipv6/firewall/address-list/add address=fd12:672e:6f65:8899::/64 list=allowed

IPv6 防火墙 filter 规则简要说明:

  • 处理 new 数据包,接受 established/related 数据包。
  • 丢弃来自 Internet(公网)接口/接口列表的 link-local 地址。
  • 接受来自 link-local 地址对路由器的访问,出于管理目的接受 multicast 地址,并接受源 address-list 用于路由器访问。
  • 丢弃其他所有内容。
/ipv6/firewall/filter
add action=accept chain=input comment="allow established and related" connection-state=established,related
add chain=input action=accept protocol=icmpv6 comment="accept ICMPv6"
add chain=input action=accept protocol=udp port=33434-33534 comment="defconf: accept UDP traceroute"
add chain=input action=accept protocol=udp dst-port=546 src-address=fe80::/10 comment="accept DHCPv6-Client prefix delegation."
add action=drop chain=input in-interface=in_interface_name log=yes log-prefix=dropLL_from_public src-address=fe80::/10
add action=accept chain=input comment="allow allowed addresses" src-address-list=allowed
add action=drop chain=input
/ipv6/firewall/address-list
add address=fe80::/10 list=allowed
add address=xxxx::/48 list=allowed
add address=ff02::/16 comment=multicast list=allowed

警告

在某些使用 DHCPv6 relay 的配置中,数据包的源地址可能不属于 link-local 范围。此时,必须移除或调整第 4 条规则的 src-address 参数,以接受 relay 地址。

保护 LAN 设备

这一步比 IPv4 中的相应步骤更为重要。在 IPv4 配置中,客户端大多使用本地地址范围内的地址,并通过 NAT 转换为公网 IP,因此无法从公网网络直接访问。

IPv6 则不同。在大多数常见配置中,启用 IPv6 会使你的客户端可从公网网络访问,因此必须配置合适的防火墙 filter 规则来保护你的客户。

简而言之,最基本的 LAN 保护应当:

  • 接受 established/related,并处理 new 数据包。
  • 丢弃 invalid 数据包。
  • 接受 ICMPv6 数据包。
  • 只接受由你的客户端发起到公网的新连接。
  • 丢弃其他所有内容。
/ipv6/firewall/filter
add action=accept chain=forward comment=established,related connection-state=established,related
add action=drop chain=forward comment=invalid connection-state=invalid log=yes log-prefix=ipv6,invalid
add action=accept chain=forward comment=icmpv6 in-interface=!in_interface_name protocol=icmpv6
add action=accept chain=forward comment="local network" in-interface=!in_interface_name src-address-list=allowed
add action=drop chain=forward log-prefix=IPV6

RAW 过滤

防火墙 RAW 表允许在连接跟踪之前选择性地绕过或丢弃数据包,从而显著降低 CPU 负载。该工具在缓解 DoS/DDoS 攻击方面非常有用。

IPv4 的 RAW filter 配置可通过 /ip/firewall/raw 菜单访问,IPv6 则通过 /ipv6/firewall/raw 菜单访问。

RAW 表没有依赖连接跟踪的匹配器(如 connection-state、layer7 等)。 如果数据包被标记为绕过连接跟踪,则不会进行数据包去分片。

此外,RAW 防火墙只能有两条链的规则:

  • prerouting —— 用于处理任何进入路由器的数据包。
  • output —— 用于处理源自路由器、并从某个接口离开路由器的数据包。穿过路由器转发的数据包不会按 output 链的规则处理。

基本 RAW 示例

假设我们配置了 OSPF,但由于连接跟踪,OSPF 出现了邻接关系问题。我们可以使用 RAW 规则来修复,方法是不把 OSPF 数据包送入连接跟踪。

/ip/firewall/raw
add chain=prerouting protocol=ospf action=notrack
add chain=output protocol=ospf action=notrack

延伸阅读