OpenWrt Router and Mihomo Side Router Setup Guide

Compare three ways to run mihomo on OpenWrt: as the main router, as a side-router gateway, or as a transparent proxy. Learn how to choose hardware, place the kernel binary, and route LAN traffic.

Choose a Deployment: Map the Gateway Path, Then Pick a Traffic-Handling Method

Running mihomo on OpenWrt involves two separate decisions: which device runs the kernel, and how LAN traffic reaches it. Treat these separately to pinpoint whether a problem lies in the config, DNS, routing, or firewall.

mihomo is the kernel used by the Clash Meta project and its continuation. It parses configuration, matches rules, and selects an outbound. LuCI management plugins operate at a separate layer, typically generating configuration, installing firewall rules, and managing the process. Copying the kernel onto a router does not automatically route every device's traffic through it.

SetupTraffic pathBest forWhat to check
Run on the main routerOpenWrt is the devices' default gatewayCentrally managing devices across the networkResource use, firewall rules, and recovery access
Side-router gatewaySome devices use the side router as their gatewayKeeping the existing main router while testing with a small groupForwarding, return path, and DNS settings
Transparent proxyTraffic is redirected through REDIRECT, TPROXY, or TUNApps that cannot be configured with a proxy address individuallyKernel modules, policy routing, and traffic exclusions

Hardware: Check the Architecture, Memory, and Storage

Check the system information from an OpenWrt SSH session before choosing a Linux kernel binary. Don't guess the architecture from the router's case model or the processor's marketing name; devices in the same product line may use different chips.

uname -m
ubus call system board
cat /etc/openwrt_release
df -h /overlay /tmp
free -m
  • x86_64 usually means amd64, but check the CPU instruction-set level required by the release build. Older processors may not support newer optimized builds.
  • aarch64 usually means arm64. For 32-bit ARM, check the ARM version and floating-point support; an arm64 binary won't work.
  • For MIPS devices, check the endianness and specific build requirements. OpenWrt package architecture names may not match upstream binary filenames exactly.
  • /tmp is usually a memory-backed filesystem and is cleared on reboot. Downloads, extraction, and logs all consume available memory; free flash storage is not the same as free memory.

Estimate capacity based on workload

Memory use depends on factors such as subscription size, rule-set size, connection count, DNS cache, and log level. No single memory threshold guarantees that mihomo will run reliably. Load your actual configuration and monitor usage before enabling startup; large rule sets may also require extra download space and persistent storage.

If the process exits shortly after starting, check logread for out-of-memory messages or records that the process was killed. For Exec format error, check the architecture and make sure the archive was extracted. For Illegal instruction, check CPU instruction-set compatibility.

Kernel and Config: Verify the Files Before Managing the Service

For a manual setup, this guide uses /usr/bin/mihomo for the kernel binary, /etc/mihomo as the working directory, and /etc/mihomo/config.yaml as the main config. If a LuCI management plugin is installed, use its designated kernel directory and config path. Don't start a second instance alongside it.

Manual setup: checks in order

  1. Back up your existing network, firewall, and DNS settings. Make sure you can reconnect to the router over a local Ethernet connection.
  2. Upload the matching, extracted kernel binary to /tmp/mihomo. Prepare the config separately so you don't overwrite a working one.
  3. Make sure the target directory has enough space, then copy the kernel binary and make it executable.
  4. Check the version and test the config first. If the test passes, start mihomo in the foreground and watch the logs.
mkdir -p /etc/mihomo
cp /tmp/mihomo /usr/bin/mihomo
chmod 755 /usr/bin/mihomo

/usr/bin/mihomo -v
/usr/bin/mihomo -t -d /etc/mihomo -f /etc/mihomo/config.yaml
/usr/bin/mihomo -d /etc/mihomo -f /etc/mihomo/config.yaml

Make sure config.yaml exists before running these commands. Use -v to check the version and -t to test the config. A successful test doesn't mean upstream nodes are reachable or that LAN traffic is flowing through the kernel. Some configs also depend on rule sets, geodata, or external files. If the first test fails, check the working directory and download logs too.

Minimal direct-connection config: check the process and listeners

This standalone test file has no proxy nodes, so all connections go direct. Use it to rule out YAML, port, and process-startup issues; it does not test proxy connectivity.

mixed-port: 7890
allow-lan: false
bind-address: "127.0.0.1"
mode: rule
log-level: info

external-controller: "127.0.0.1:9090"

dns:
  enable: true
  listen: "127.0.0.1:1053"
  enhanced-mode: redir-host
  nameserver:
    - 223.5.5.5

rules:
  - MATCH,DIRECT

In this example, 7890 is the mixed HTTP/SOCKS proxy port, 9090 is the controller port, and 1053 is the DNS listener. They are not interchangeable. After verifying the process in the foreground, use a management plugin or OpenWrt's procd to start, stop, and restart it. Don't run the same kernel instance through a plugin, a custom service, and a background command at the same time.

Run on the Main Router: Centralized Traffic and DNS

Running mihomo on the main router means devices already pass through it, so you don't need to change each device's gateway. The tradeoff is that a firewall or DNS mistake can affect the entire LAN. Start with one test device or subnet, then expand the scope gradually.

Check the existing settings in LuCI

  • Go to Network → Interfaces → LAN → Edit and note the LAN address and subnet mask.
  • Under LAN → DHCP Server, check the address pool and DHCP options. Make sure no other device is assigning a conflicting gateway.
  • Go to Network → Firewall and make sure the existing LAN-to-WAN forwarding rule is still in place.
  • Go to Status → System Log and check the kernel and DNS service logs. Labels may vary slightly between firmware translations and themes.

A common DNS path is for devices to query the router on port 53, with dnsmasq forwarding requests to mihomo's local port 1053. Make sure the upstream path doesn't point back to dnsmasq, which would create a DNS loop. Setting dns.listen alone won't make devices use that listener; you also need an explicit forwarding or interception rule.

Side-Router Gateway: Test the Outbound and Return Paths on One Device

A single-port side router is often on the same subnet as the main router. In this example, the main router is 192.168.50.1/24, the side router is 192.168.50.2/24, and the test device is 192.168.50.100/24. These addresses are examples only; avoid conflicts with existing DHCP pools and devices before deployment.

  1. Assign the side router a static LAN address of 192.168.50.2 and set its upstream default gateway to 192.168.50.1.
  2. For now, let only the main router serve DHCP to avoid two devices assigning addresses on the same broadcast domain.
  3. On one test device, manually set the default gateway to 192.168.50.2.
  4. If the side router provides DNS service to the LAN, set the test device's DNS server to 192.168.50.2 as well. Otherwise, test routing on its own first.
  5. Check that the side router allows the required forwarding path and that the return path for direct traffic matches your design.

In this same-subnet setup, direct traffic may pass through the side router to the main router, while replies go straight from the main router to the device, creating an asymmetric path. Whether you need source NAT, a static route on the main router, or a separate subnet depends on the firewall's connection tracking and network topology. Neither “always disable NAT on a side router” nor “always enable NAT” is a substitute for checking.

Verify the gateway and DNS separately

Changing the gateway only determines the next hop for IP packets; it doesn't guarantee that DNS queries also pass through the side router. Encrypted DNS in browsers, static DNS settings on devices, and IPv6 router advertisements can create separate paths. First check the test device's actual IPv4 gateway, IPv6 default route, and DNS addresses, then decide whether traffic interception is needed.

After a single-device test succeeds, you can consider using the main router's DHCP options to set option 3 for the IPv4 default gateway and option 6 for DNS. Some home routers don't support setting these options individually. In that case, keeping manual settings or using a separate test subnet is easier to roll back than switching the whole network at once.

Transparent Proxy: REDIRECT, TPROXY, and TUN Compared

With an explicit proxy, apps connect directly to a proxy port such as 7890. A transparent proxy uses routing and firewall rules to send original connections to the kernel. Both entry points can coexist, but make sure multiple rule sets don't intercept the same connection more than once.

Methodmihomo fieldDeployment notes
REDIRECTredir-portPrimarily for redirecting TCP; this alone does not mean UDP is intercepted
TPROXYtproxy-portSupports TCP and UDP; requires transparent proxy support, packet marks, and policy routing
TUNtun.enableRoutes traffic through a virtual network interface; requires TUN support and correctly scoped routes

OpenWrt 22.03 and later commonly use firewall4 with nftables by default. Don't paste iptables rules from older guides into a newer setup without checking them. Also check whether your firmware uses a custom firewall backend and whether the required modules are installed.

Enabling TUN doesn't mean LAN traffic is fully intercepted

tun.auto-route configures related routes automatically, but the result depends on the system, version, and network topology. This field alone doesn't prove that all forwarded traffic enters TUN. tun.auto-redirect also has platform and version requirements and won't work the same way in every Linux environment. If a plugin manages traffic interception on your router, let it generate the rules; don't add a second set of manual rules on top.

  • Exclude the router's management address, required local subnets, and connections from the kernel to upstream proxy servers to avoid routing loops.
  • When using fake-ip, make sure the virtual address range returned by DNS has a matching route and interception path. Otherwise, DNS resolution may succeed while connections fail.
  • For apps that need UDP, check the traffic entry method, node protocol support, and server capabilities. Working TCP web access doesn't prove UDP is working.
  • Check IPv4 and IPv6 separately. Configuring transparent proxying for IPv4 does not automatically cover IPv6 connections.

Connect LAN Devices: Start with an Explicit Proxy, Then Check Rule Matches

Before enabling traffic interception, test with an explicit proxy on one device to isolate forwarding issues. To make the test config's 7890 port accessible from the LAN, set allow-lan to true and bind-address to the actual LAN address, such as "192.168.50.2". Use the firewall to allow access only from trusted subnets.

Don't expose proxy ports or the controller interface through WAN port forwarding. Keeping external-controller bound to localhost is generally easier to secure. If remote management is required, set a strong secret and restrict the allowed sources. Controller authentication and authentication for a mixed proxy port are separate settings and cannot replace each other.

Narrow down issues layer by layer

  1. Process: Make sure the config test passes, the kernel keeps running, and no second instance is competing for ports.
  2. Traffic entry: Make sure the device can connect to the proxy port on the LAN address. For connection refusals, check the listener address first; for timeouts, check the firewall and network path.
  3. Outbound: Use a working node and proxy group, then check authentication, protocol, and upstream connectivity. The direct-connection test config above does not provide proxy access.
  4. Rules: Check that mode: rule is set, then review the matching rule and outbound policy in the logs. Rules are matched from top to bottom; an early catch-all rule can prevent later rules from being reached.
  5. Traffic interception: If the explicit proxy works but the transparent proxy doesn't, check DNS, policy routing, the firewall, and IPv6 first. Don't start by repeatedly changing subscriptions.

Assess kernel resource use and node speed separately. Slow first-byte response may point to DNS or connection setup; slow large-file transfers may also be affected by CPU load, encryption, line capacity, or congestion. Record the timing, test device, destination, and matched policy to make the issue easier to reproduce than simply noting that the “side router is slow.”

Updates and Rollback: Keep a Working Config and a Separate Way to Manage the Router

Update subscriptions, upgrade the kernel, and change firewall rules separately. A subscription update may replace nodes, proxy groups, and rules; a management plugin may regenerate the runtime config at startup. Put lasting changes in the plugin's supported override or custom-rule settings rather than editing a temporary generated file.

  • Before upgrading, record the output of mihomo -v and keep a working kernel binary, main config, and custom rules.
  • Stop the old process before replacing the binary. Test the config first, then start the service; don't overwrite a binary that is currently running.
  • Check the startup results with logread, confirm that rule resources load, then test DNS, TCP, and any apps that need UDP.
  • Keep one device that can connect directly to the router's management address. If the side router fails, restore the test device's gateway and DNS to the main router. If you changed DHCP options, restore them and renew the device's lease.

If you only need a proxy on one computer or phone, installing the client for that platform is usually simpler. Move the gateway, DNS, and transparent proxy setup to a router only if you need centralized access for TVs, game consoles, or multiple devices. For YAML basics and rule order, see the config file structure and rule field reference.

Download ClashChoose a client for your platform