Route leaking between VRFs does not work: gateway is vrf@vrf

The documentation recommends using bgp vpn to leak routes between VRFs.

This works but the imported routes are non-functional as their gateway is vrf@vrf.

In my example, I have many interfaces in vrf-main and another vrf-wwan which only contains the internet uplink. For my vrf-main to be able to access the internet, I am leaking the default gateway via static route. However, for the return packets, vrf-wwan needs to know all my prefixes from vrf-main, right?

In this example, I am configuring the BGP routes to export all connected routes from vrf-main and importing them into vrf-wwan:

[admin@SunGate2] /routing/bgp/vpn> export 
# 2025-11-16 01:25:04 by RouterOS 7.21beta7
# system id = 4266Dgl372D
#
/routing bgp vpn
add disabled=no export.redistribute=connected import.route-targets=1:100 instance=bgp-virtual-instance label-allocation-policy=\
    per-prefix name=bgp-mpls-vpn-1 route-distinguisher=1:1 vrf=vrf-wwan
add disabled=no export.redistribute=connected .route-targets=1:100 instance=bgp-virtual-instance label-allocation-policy=per-prefix \
    name=bgp-mpls-vpn-2 route-distinguisher=1:1 vrf=vrf-main

    

This works. However, I cannot ping any internet address from vrf-main. The issue is that all my routes are imported as vrf-main@vrf-main gateway. This is total BS! With the packet sniffer I can see the router sending the packet into interface “vrf-main” but that’s wrong, it must go into vlan4!!

If I manually create the route it works.

[admin@SunGate2] /ip/route> print without-paging 
Flags: D - DYNAMIC; X - DISABLED, I - INACTIVE, A - ACTIVE; c - CONNECT, s - STATIC, d - DHCP, y - BGP-MPLS-VPN; + - ECMP
Columns: DST-ADDRESS, GATEWAY, ROUTING-TABLE, DISTANCE
#      DST-ADDRESS         GATEWAY                 ROUTING-TABLE  DISTANCE
[...]
  DAy  10.227.4.0/24       vrf-main@vrf-main       vrf-wwan            200
  DAy  10.227.4.254/32     vrf-main@vrf-main       vrf-wwan            200
[...]
  DAc  10.227.4.0/24       vlan4@vrf-main          vrf-main              0
  DAc  10.227.4.254/32     vrrp4@vrf-main          vrf-main              0
[...]




What is the issue?

vrf must know where to send return traffic

I picked this up again and migrating my dozens of static route leaks and now I am facing this exact issue again.

I am 100% confident that traffic doesn't pass because the route target is vrf@vrf instead of interface@vrf.

Anyone else facing this?

This is really absolutely the same as described in the documentation!

PS: It's not a firewall issue, I have temporarily enabled all INPUT and FORWARD for testing. Here is a packet sniffer shot from (a) the working case with static route leak (b) the dynamic case. In this test, a host in vrf-main (on interface vlan3, 10.227.79.104) is pinging www.kernel.org, reachable via vrf-wwan. It's evident that the issue is that the return packet is sent via vrf-main device instead of vlan3. That seems to be a black hole. Why the heck does documentation say this could possibly work?

Routing table for case 1 (working):

/routing/route/print detail where dst-address=10.227.79.0/24 and routing-table=vrf-fiber
Flags: X - DISABLED, F - FILTERED, U - UNREACHABLE, A - ACTIVE;
c - CONNECT, s - STATIC, r - RIP, b - BGP, n - BGP-NET, o - OSPF, i - ISIS, d - DHCP, v - VPN, m - MODEM, a - LDP-ADDRESS, l - LDP-MAPPING>
H - HW-OFFLOADED; + - ECMP, B - BLACKHOLE
y   afi=ip contribution=best-candidate dst-address=10.227.79.0/24 routing-table=vrf-fiber gateway=vrf-main@vrf-main
immediate-gw=vrf-main distance=200 scope=20 target-scope=10 belongs-to="bgp-mpls-vpn-2-vrf-main-connected-export-import"
bgp.ext-communities=rt:64512:100 .origin=incomplete
route-distinguisher="64512:1"
debug.fwp-ptr=0x203045A0

As   afi=ip contribution=active dst-address=10.227.79.0/24 routing-table=vrf-fiber gateway=vlan3@vrf-main immediate-gw=vlan3 distance=1
scope=30 target-scope=10 belongs-to="static"
debug.fwp-ptr=0x203020C0

Routing table for case 2 (not working):

/routing/route/print detail where dst-address=10.227.79.0/24 and routing-table=vrf-fiber
Flags: X - DISABLED, F - FILTERED, U - UNREACHABLE, A - ACTIVE;
c - CONNECT, s - STATIC, r - RIP, b - BGP, n - BGP-NET, o - OSPF, i - ISIS, d - DHCP, v - VPN, m - MODEM, a - LDP-ADDRESS, l - LDP-MAPPING>
H - HW-OFFLOADED; + - ECMP, B - BLACKHOLE
Xs   contribution=(unknown) dst-address=10.227.79.0/24 routing-table=vrf-fiber gateway=vlan3@vrf-main distance=1 scope=30
target-scope=10

Ay   afi=ip contribution=active dst-address=10.227.79.0/24 routing-table=vrf-fiber gateway=vrf-main@vrf-main immediate-gw=vrf-main
distance=200 scope=20 target-scope=10 belongs-to="bgp-mpls-vpn-2-vrf-main-connected-export-import"
bgp.ext-communities=rt:64512:100 .origin=incomplete
route-distinguisher="64512:1"
debug.fwp-ptr=0x203045A0

Hello Everyone,

I was about to post on same subject
Injected VPNv4 routes between VRF on same mikrotik ver 7.21 is not working,

Exchange two connected routes from VRF A and VRF B

I see in routing table of VRF A

DAy Connected Subnet VRF B VRFB@VRFB 200 VRF A

VRF B

Day Connected Subnet VRF A VRFA@VRFA 200 VRF B

It kind mute point VRF by it self can’t route unless interface get involved.

I can’t provide full details protected network no internet. Sorry :slight_smile:

I thought about filter and set gateway, but it connected networks no next hop.
Mikrotik should provide some feedback seems like next hop selector got confused.
Expecting just VRF%VRF type route.

Work around which works to force next hop lookup

In /routing/rule

add dst-address=Connected Subnet VRF A@VRF B action=lookup table=VRF A
add dst-address=Connected Subnet VRF B@VRF A action=lookup table=VRF B

But again mikrotik need to check.

do not use /ip/route , the right way is traffic mark in firewall

  1. mark the connection,chain=prerouting in-interface=vrf-main new-connection-mark=conn_vrf-main
  2. routing to where you want ,eg. main vlan10 , chain=prerouting connection-mark=conn_vrf-main in-interface=vrf-main new-routing-mark=main (that will match the default gw)
  3. The most important thing is to return the package, base on the connection, catch the return-packet to vrf-main , chain=prerouting connection-mark=conn_vrf-main in-interface=vlan10 new-routing-mark=vrf-main

in this way , main routing-table dont need to know any your prefix of vrf-main