Firewall not matching interface in VRF

I’m experiencing an issue on 7.22.1 where a firewall rule targeting a VRF interface using out-interfacedoes not actually match interfaces within that VRF.

I have a setup where I have two VRFs. One VRF is my internet transit VRF, containing a default route from my ISP. Another is my user VRF, containing all my internal user networks. I’m leaking a default route to the user VRF and the user subnets to the ISP VRF. My route table looks like this

Flags: D - DYNAMIC; I - INACTIVE, A - ACTIVE; c - CONNECT, d - DHCP, y - BGP-MPLS-VPN
Columns: DST-ADDRESS, GATEWAY, ROUTING-TABLE, DISTANCE
    DST-ADDRESS     GATEWAY                                   ROUTING-TABLE        DISTANCE
DAd 0.0.0.0/0       203.0.113.1@vrf_isp_transit               vrf_isp_transit             1
DAy 10.1.0.0/23     vrf_user@vrf_user                         vrf_isp_transit           200
DAc 203.0.113.0/24  vlan_isp_transit@vrf_isp_transit          vrf_isp_transit             0
DAy 0.0.0.0/0       203.0.113.1@vrf_isp_transit               vrf_user                  200
DAc 10.1.0.0/23     vlan_user_1@vrf_user                      vrf_user                    0
DAy 203.0.113.0/24  vrf_isp_transit@vrf_isp_transit           vrf_user                  200

I have a src nat masquerade rule that matches traffic exiting the vlan_isp_transit interface.

Flags: X - DISABLED, I - INVALID; D - DYNAMIC 
 0    ;;; isp_src_nat
      chain=srcnat action=masquerade out-interface=vlan_isp_transit log=no log-prefix="" 

The firewall behavior I want is to allow all traffic to egress from the user VRF to the ISP VRF, and allow established/related traffic to ingress from the ISP VRF back to the user VRF. Pretty standard.

Flags: X - DISABLED, I - INVALID; D - DYNAMIC 
0     ;;; accept ISP egress
      chain=forward action=accept out-interface=vrf_isp_transit log=yes log-prefix="WAN EGRESS - " 

1     ;;; accept established/related fwd
      chain=forward action=accept connection-state=established,related log=no log-prefix="" 

3     ;;; default drop fwd
      chain=forward action=drop log=yes log-prefix="DROP FWD" 

Now, the documentation states the following when it comes to matching interfaces within a VRF.

Before RouterOS version 7.14, firewall filter rules with the property in/out-interface would apply to interfaces within a VRF instance. Starting from RouterOS version 7.14, these rules no longer target individual interfaces within a VRF, but rather the VRF interface as a whole.

The vlan_isp_transit interface which is connected to the next hop for the default route is within the vrf_isp_transit VRF. So, I’d expect rule 0 to match any traffic being forwarded across this interface, because of the out-interface rule matching the ISP VRF as a whole.

However, the behavior I see is that the traffic is not actually matched – it’s dropped.

DROP FWD -  forward: in:vrf_user out:vlan_isp_transit, connection-state:new src-mac 64:4B:F0:10:54:81, proto ICMP (type 8, code 0), 10.1.0.27->1.1.1.2, len 84

Clearly, rule 0 which is supposed to match any traffic egressing via an interface within the vrf_isp_transit VRF, is not being matched. This seems like a bug or at least is behaving contrary to the documentation.

Yes, currently, and up to the dev version 7.23beta5, there is an issue with matching out-interface=<vrf-interface> (and you cannot use the real interface here). It works with in-interface=<vrf-interface> though.

As workaround, what you can do is to create an interface list, for example VRF_ISP_TRANSIT and add the real interface into that list, in your case, add vlan_isp_transit, do not add the VRF interface vrf_isp_transit.

Afterwards you can use the condition out-interface-list=VRF_ISP_TRANSIT in your forward filter rule, and it will work as expected.