Mihomo TUN Mode Breaks Networking: Ip_forward, UFW, and Auto-Redirect
When using mihomo in TUN mode (stack: system, auto-route: true), enabling it causes a complete network outage — SSH drops too. The problem isn’t in the mihomo config itself, but in system network forwarding settings that aren’t configured.
Cause
stack: system makes mihomo rely on the kernel networking stack to forward TUN traffic. auto-route: true takes over the default route and funnels all traffic into the TUN interface. But the kernel needs three conditions to forward:
net.ipv4.ip_forwardmust be1- The firewall forward chain must not DROP
- The kernel must not drop TCP packets returning from the TUN interface due to rp_filter
Arch Linux defaults to ip_forward=0, and UFW defaults to DEFAULT_FORWARD_POLICY="DROP". Both block forwarding. Even after fixing those two, on kernel 6.x ping works but curl times out — TCP handshake packets returning from the TUN interface are dropped by rp_filter=1. The mihomo log shows [TCP] ... using DIRECT, but the connection just times out.
Fix
1. Enable ip_forward
echo 'net.ipv4.ip_forward = 1' | sudo tee /etc/sysctl.d/99-mihomo.conf
sudo sysctl -p /etc/sysctl.d/99-mihomo.conf2. Change UFW forward policy to ACCEPT
sudo sed -i 's/DEFAULT_FORWARD_POLICY="DROP"/DEFAULT_FORWARD_POLICY="ACCEPT"/' /etc/default/ufw
sudo ufw reload3. Enable auto-redirect
Add auto-redirect: true to the tun section in config.yaml:
tun:
enable: true
stack: system
auto-route: true
auto-redirect: true
auto-detect-interface: trueauto-redirect automatically configures nftables rules to redirect TCP connections, bypassing rp_filter’s filtering of return packets from the TUN interface. Restart mihomo after changing.
Alternative
If you don’t want to change system forwarding settings, switch the TUN stack:
mixed: TCP uses the system stack, UDP uses gvisor — better compatibility than system, better performance than pure gvisorgvisor: handles TCP/IP entirely in userspace without relying on kernel forwarding — best compatibility but slightly lower performance
Change tun.stack in config.yaml from system to mixed or gvisor. No system configuration changes needed.