[FIXED] RouterOS 7.22+ Container TUN Gateway Broken (sing-box / mihomo)

:fire: Problem

After upgrading to RouterOS 7.22:

  • TUN gateway inside container stops working

  • Traffic does NOT enter container

  • Setting container as gateway has no effect

Works fine on 7.20.8 / 7.21, broken on 7.22+

If your TUN gateway does not work on RouterOS 7.22+,
DO NOT debug proxy config first — check ip rule.


:brain: Root Cause

RouterOS 7.22 changed default ip rule priorities inside container:

1: from all lookup local
2: from all lookup main
3: from all lookup default

This breaks:

  • policy routing

  • fwmark routing

  • TUN-based proxy cores


:white_check_mark: Fix

Normalize ip rule order before launching proxy core:

ip rule del pref 1
ip rule del pref 2
ip rule del pref 3

ip rule add pref 200 from all lookup local
ip rule add pref 2147483646 from all lookup main
ip rule add pref 2147483647 from all lookup default

:package: Provided

  • Prebuilt sing-box container (fixed)

  • Prebuilt mihomo container (fixed)

  • Full deployment guide (RB5009 tested)


:test_tube: Tested

  • Device: RB5009

  • OS: RouterOS 7.22

  • Mode: Container + TUN Gateway

  • Result: :white_check_mark: Fully working


:light_bulb: Conclusion

This is NOT:

  • sing-box issue

  • mihomo issue

  • config issue

:backhand_index_pointing_right: This is a RouterOS container routing regression

RB5009 / RouterOS 7.22+ Container TUN Fix**(sing-box / mihomo)**
Root cause: default ip rule priority regression in RouterOS container environment
Fix: normalize ip rule order before launching proxy core

Many thanks to CGGXANNX and Gundolf for their replies. The issue of container tun0 failing on version 7.22.1 has been completely fixed, and the latest versions of the singbox and mihomo images have been backed up. They can be imported directly and will work. The shared directory contains a detailed workflow document, RB5009-ROS722-TUN-Final Instructions.pdf, which you can check out if you're interested.

Additionally, I recommend using a node conversion tool to generate the configuration file:https://sublink.works
mihomo For tun mode, you need to add a tun configuration endpoint; simply paste it below the DNS section. The code is as follows:

entrypoint=/entrypoint.sh,No other settings required:

tun:
  enable: true
  device: tun0
  stack: system
  auto-route: true
  auto-detect-interface: true
  strict-route: true
  dns-hijack:
    - any:53

This is the complete IP rule startup command for entrypoint.sh. If you are creating your own image, you can refer to it directly:

#!/bin/sh
set -eu

LOG_FILE="/startup.log"

log() {
  printf '%s\n' "$*" | tee -a "$LOG_FILE"
}

ensure_ip_rule_priorities() {
  while ip rule show | grep -Eq '^1:\s+from all lookup local'; do
    ip rule del pref 1 >/dev/null 2>&1 || break
  done
  while ip rule show | grep -Eq '^2:\s+from all lookup main'; do
    ip rule del pref 2 >/dev/null 2>&1 || break
  done
  while ip rule show | grep -Eq '^3:\s+from all lookup default'; do
    ip rule del pref 3 >/dev/null 2>&1 || break
  done

  ip rule add pref 200 from all lookup local >/dev/null 2>&1 || true
  ip rule add pref 2147483646 from all lookup main >/dev/null 2>&1 || true
  ip rule add pref 2147483647 from all lookup default >/dev/null 2>&1 || true
}

: > "$LOG_FILE"
log "[start]"

ensure_ip_rule_priorities

# fake-ip 开启才需要
ip route add 198.18.0.0/15 dev tun0 >/dev/null 2>&1 || true

log "[launch sing-box]"
exec /bin/sing-box run -c /config.json --disable-color

RB5009UG+S+ 7.22 singbox+mihomo Download

https://drive.google.com/drive/folders/1YTVe9rqMn2YzbFZPkyYn6zjeUQKpf-uT?usp=sharing

Detailed workflow:

https://drive.google.com/file/d/14fn8Llyzc28fwrHptqLZr7Nx9gYXbniq/view?usp=sharing

I have the same issue.

7.20.8 / 7.21.3 - IP forwarding inside the container works correctly.

7.22 / 7.23beta2 - It doesn’t work correctly.

Did you manage to fix it?

No, the forwarding efficiency within the container is too low, especially since the performance of 5009 is insufficient. I currently use an x86 host to install Server 2019, and use an Alpine virtual machine installed with Hyper-V as a transparent gateway. I run Singbox directly using the binary and configuration file. The advantage is faster access, more flexible configuration, and I don't have to worry about ROS container failures anymore. If you can only use ROS, then stay on the current usable version and don't update it.

Adding the line fake-ip to the command prompt (cmd) will make the route work; keep everything else unchanged. The line should be;

-c "sleep 3 && ip route add 198.18.0.0/15 dev tun0"

Any official news about a fix for this in routeros? Wasted a few hours on this before noticing this post.
Judging by the release notes, even 7.23 won’t fix this?

If I am not mistaken, sing-box TUN makes use of iproute2 rules. If that's the case then it's probably affected by this issue introduced by 7.22:

If you can open a shell into the container (with /container shell) and run the ip rule command, you'll probably see that sing-box is able to properly insert its routing rules between

200:    from all lookup local 

and

2147483646:     from all lookup main 

under version 7.20.x. However under 7.22+, because the default rules now look like this:

1:      from all lookup local 
2:      from all lookup main 
3:      from all lookup default

The rule added by sing-box will be at the bottom of the table and are no longer effective.

If that's the case, the bug report that you send to MikroTik should mention this routing rule issue as the bug, do not mention that as a sing-box specific bug. Because MikroTik are less reluctant to install 3rd party softwares to test compatibility bug. If you can pinpoint the problem to the default routing rules, then could reproduce the problem more easily.

Thank you for the explanations. I’ve set my entrypoint to ensure the ip rules are the same as 7.21 and now things are working in 7.23 rc1:

# https://forum.mikrotik.com/t/routeros-7-22-regression-containerized-sing-box-tun-gateway-works-on-7-20-8-but-fails-on-7-22/269160/6
ensure_ip_rule_priorities() {
while ip rule show | grep -Eq '^1:\s+from all lookup local(\s|$)'; do
ip rule del pref 1 >/dev/null 2>&1 || break
done
while ip rule show | grep -Eq '^2:\s+from all lookup main(\s|$)'; do
ip rule del pref 2 >/dev/null 2>&1 || break
done
while ip rule show | grep -Eq '^3:\s+from all lookup default(\s|$)'; do
ip rule del pref 3 >/dev/null 2>&1 || break
done

if ! ip rule show | grep -Eq '^200:\s+from all lookup local(\s|$)'; then
ip rule add pref 200 from all lookup local >/dev/null 2>&1 || true
fi
if ! ip rule show | grep -Eq '^2147483646:\s+from all lookup main(\s|$)'; then
ip rule add pref 2147483646 from all lookup main >/dev/null 2>&1 || true
fi
if ! ip rule show | grep -Eq '^2147483647:\s+from all lookup default(\s|$)'; then
ip rule add pref 2147483647 from all lookup default >/dev/null 2>&1 || true
fi
}

ensure_ip_rule_priorities

Edit: works on 7.22.1 too.

The issue of container tun0 not working on version 7.22.1 has been completely fixed, and the latest versions of the singbox and mihomo images have been backed up. Simply import them to work. See the link at the bottom of the article.

Thank you very much for your reply. The issue of container tun0 not working on version 7.22.1 has been completely fixed. I have also backed up the latest versions of the Singbox and Mihomo images; they can be imported directly and will work. See the link at the bottom of the article.

Thank you very much for your reply. The issue of container tun0 not working on version 7.22.1 has been completely fixed. I have also backed up the latest versions of the Singbox and Mihomo images; they can be imported directly and will work. See the link at the bottom of the article.

The routing rule priority in container has been corrected in 7.23rc2:

image