Run mihomo Directly on an OpenWrt Side Router: Deployment Guide
Compare main router and side-router roles, mihomo binaries and config paths, transparent proxy options, and gateway settings to choose the right OpenWrt setup.
Choose a setup: test a manual proxy before routing gateway traffic
Running mihomo directly on OpenWrt means having the system start the core process, load a YAML config, and connect it to the router and firewall as needed. mihomo is the core commonly known as Clash Meta; it is not a LuCI plugin, and copying it onto a router will not automatically route traffic for your whole network. The web interface, subscription updates, transparent proxy rules, and startup service all need to be configured separately.
For a safer setup, work through three stages: first validate the config, then test an explicit proxy from one computer, and only then change that computer’s default gateway and DNS. Each stage gives you a clear checkpoint, making it easier to identify problems and roll back one step at a time.
| Setup | How devices connect | What you need to configure |
|---|---|---|
| Explicit proxy | Manually enter the side router’s IP address and port 7890 | Core, config, and LAN access permissions |
| TUN routing | Set the device’s gateway to the side router | TUN device, routes, DNS, firewall, and IPv6 |
| Transparent proxy via firewall | Set the device’s gateway to the side router | REDIRECT or TPROXY, policy routing, and loop prevention |
If you only need a proxy in your browser, the first option is enough. The other two are worth exploring if you want to connect a TV, gaming device, or app that does not support manual proxy settings. If your OpenWrt device already has a management plugin, check whether it is running mihomo before proceeding; avoid having two management tools compete for control of ports and routes.
Main router and side router: map the traffic flow first
This guide uses a sample IPv4 LAN to explain how the two routers work together. The main router handles the internet connection and DHCP; the side router has a fixed address and initially serves only one test device. These addresses are examples—check your existing subnet and address assignments before applying them.
- Main router:
192.168.10.1/24, connected to the internet. - OpenWrt side router:
192.168.10.2/24, with192.168.10.1as its upstream gateway. - Test computer:
192.168.10.100/24, initially using the main router as its gateway. - Example DHCP pool:
192.168.10.100–192.168.10.200. Keep the side router’s address outside the dynamic pool.
Give the side router a fixed address and keep DHCP on one router
In the standard LuCI interface, go to Network → Interfaces → LAN → Edit and check the static IPv4 address and upstream gateway. Labels may vary slightly between themes. Under DHCP Server for the side router’s LAN interface, the usual setting is to enable Ignore interface so it does not assign addresses alongside the main router. Keep a wired connection available and note the new address before changing the management IP.
With a single-arm side router on the same subnet, incoming and outgoing traffic may use the same LAN interface. This differs from a two-port router with separate LAN and WAN interfaces, and return traffic may take an asymmetric path. Whether to use source NAT or how to handle ICMP redirects depends on your firewall and transparent proxy setup. Don’t paste firewall commands from another device without checking how they apply to yours.
The side router’s upstream gateway should always point to the main router, never to itself. Before switching over, leave DHCP on the main router unchanged and adjust only one test device.
Core and directories: check architecture, permissions, and config paths first
Start by checking the hardware and firmware over SSH. Run uname -m to check the kernel architecture, ubus call system board to see the board and system details, and df -h to check storage. When choosing a mihomo release, also check its CPU instruction-set requirements. Two devices with x86_64 processors may still differ in which builds they can run.
uname -m
ubus call system board
df -h
free -m
ls -l /dev/net/tun
Without /dev/net/tun, you can still test an explicit proxy first; install the required kernel modules before enabling TUN. OpenWrt kernel modules must match the firmware’s kernel version—never force-install modules built for another version. The package manager may be opkg or apk; check which one your firmware uses.
Use these three fixed paths
/usr/bin/mihomo: the extracted core executable, not the compressed archive./etc/mihomo/config.yaml: the active config file./etc/mihomo/: the working directory for referenced rules, databases, and runtime data.
Upload a core build for the matching architecture, set it as executable, and check its version. Configs may contain subscription URLs, node passwords, or tokens, so restrict file permissions and don’t post them in public forums.
mkdir -p /etc/mihomo
chmod 755 /usr/bin/mihomo
/usr/bin/mihomo -v
chmod 600 /etc/mihomo/config.yaml
/usr/bin/mihomo -t -d /etc/mihomo -f /etc/mihomo/config.yaml
The final command checks the config. If it reports invalid fields, use the logs to fix YAML indentation or incompatible options. If rule files or geolocation databases are missing, check their paths and download connectivity. A successful config check only confirms that mihomo can load the file; it does not verify nodes, DNS, or transparent proxying.
Start with port 7890: test the explicit proxy before importing a subscription
This minimal config tests the listener and direct connectivity. It has no proxy nodes, so every connection uses DIRECT; it cannot tell you whether subscription nodes work. Use it to isolate deployment issues, then switch to a complete subscription config confirmed to support mihomo.
mixed-port: 7890
allow-lan: true
bind-address: "192.168.10.2"
mode: rule
log-level: info
ipv6: false
rules:
- MATCH,DIRECT
mixed-port accepts HTTP and SOCKS5 proxy connections on the same port; allow-lan lets other devices connect. The bind address must be assigned to the side router. Make sure the firewall allows TCP port 7890 only from trusted LAN devices, and don’t set up an internet-facing port forward for it on the main router.
/usr/bin/mihomo -d /etc/mihomo -f /etc/mihomo/config.yaml
Running mihomo in the foreground makes errors easier to spot. Keep this SSH session open while you run the request below from the test computer. If curl is unavailable, enter the HTTP proxy address 192.168.10.2 and port 7890 in the system or browser proxy settings.
curl -I --proxy http://192.168.10.2:7890 https://example.com
If you see HTTP response headers from the target site, the computer can reach the side router’s proxy and the core can make outbound connections. Next, load your actual config and check that proxy group names and rule targets match, then confirm which policy handles a test connection. Downloading a text file that contains a subscription link does not mean you have a ready-to-use YAML config.
The management API and proxy ports are separate endpoints. You don’t need to expose external-controller at this stage. If you add a dashboard later, set a secret and restrict which devices can reach the management port.
Transparent proxying: check the gateway, TUN, and DNS together
Once the explicit proxy works, turn off the test computer’s manual proxy and change its default gateway to 192.168.10.2. This only routes packets through the side router; without TUN routes or firewall forwarding rules, traffic will not automatically enter mihomo. A changed gateway alone does not prove transparent proxying is working.
What to know about the TUN option
mihomo’s tun.enable enables a virtual network device, auto-route automatically configures related routes, and auto-detect-interface detects the outbound interface. These options do not replace all OpenWrt firewall configuration. On a side router where LAN traffic enters and exits through the same interface, also check forwarding permissions, the kernel traffic path, excluded destinations, and return routing.
Another option is to use redir-port or tproxy-port with firewall rules. REDIRECT is commonly used for TCP redirection; TPROXY can handle TCP and UDP but requires matching policy routing. Current OpenWrt releases commonly use firewall4 and nftables, while older guides may rely on firewall3 and iptables. Don’t mix rules from the two stacks without adapting them. Nor should both approaches try to intercept the same connections.
Make sure the DNS listener matches your DHCP settings
A common setup keeps dnsmasq listening on LAN port 53 for DNS, while mihomo listens locally on 127.0.0.1:1053 and dnsmasq forwards upstream queries to it. Port 1053 is for internal forwarding, not a DNS address to enter on a phone; typical client DNS settings do not support a custom port.
- If client devices use the side router for DNS, confirm that its port 53 actually responds to queries.
- When dnsmasq forwards queries to mihomo, make sure mihomo’s upstream DNS does not point back through the same dnsmasq path, or you’ll create a resolution loop.
- With fake-IP enabled, DNS responses and subsequent connections should follow the same interception path. Otherwise, clients may get a fake address without their traffic ever reaching the core.
- Secure DNS in browsers, in-app DoH, and hard-coded DNS servers may bypass system resolver settings. Check each one separately.
Handle IPv6 separately, too. The IPv6 default route advertised by the main router won’t disappear when you change the IPv4 gateway manually. Setting ipv6: false in the config does not disable IPv6 across your LAN. During testing, you can temporarily disable IPv6 on the test device to narrow down the issue. For a full deployment, define your IPv6 routing, DNS, and traffic interception strategy.
Start on boot: use procd to manage the process, not a background command
After the foreground test succeeds, stop the process with Ctrl+C and configure it as a system service. OpenWrt uses procd to manage services; appending & in an SSH session does not provide startup or process supervision. The minimal service below only starts the core—it does not create firewall rules or schedule subscription updates.
Save the following as /etc/init.d/mihomo. If a service with that name already exists or a plugin manages the core, confirm who owns it before making changes; don’t overwrite it.
#!/bin/sh /etc/rc.common
START=99
STOP=10
USE_PROCD=1
start_service() {
procd_open_instance
procd_set_param command /usr/bin/mihomo \
-d /etc/mihomo \
-f /etc/mihomo/config.yaml
procd_set_param respawn
procd_set_param stdout 1
procd_set_param stderr 1
procd_set_param file /etc/mihomo/config.yaml
procd_close_instance
}
chmod 755 /etc/init.d/mihomo
/etc/init.d/mihomo enable
/etc/init.d/mihomo start
logread -e mihomo
Keep the last known-good config before updating a subscription. Save new content to a temporary file, run mihomo -t to validate it, then replace the active config and restart the service. If the syntax is valid but the nodes don’t work, roll back anyway. Don’t let an automatic update job repeatedly overwrite a manually repaired version. Rule sets, database downloads, and caches also use flash storage, so check free space regularly.
Verify and roll back: test one device before expanding
After deployment, work through these checks in order instead of relying only on the dashboard’s connection status. Move on only when each check passes; this makes it easier to pinpoint what went wrong if the network stops working.
- Router connectivity: The side router can reach the main router, resolve domain names, and establish HTTPS connections.
- Proxy access: When the test computer sends a request through
192.168.10.2:7890, the corresponding connection appears in the logs. - DNS response: Run
nslookup example.com 192.168.10.2and confirm the responding server is the one you expect. - Transparent routing: Turn off the explicit proxy and visit the target site. Confirm mihomo still logs the connection and applies the expected rule.
- Local network access: Check the main router’s admin page, printers, NAS devices, and local services. They should not be sent to a remote proxy by mistake.
- Recovery after reboot: Restart the side router and test again. Confirm the service, DNS, and forwarding path all recover without relying on a command you ran manually before.
If the entire network loses internet access, restore the test computer’s gateway and DNS to the main router’s original settings and disable the manual proxy. Then stop mihomo. If you added nftables rules, policy routes, or DNS forwarding manually, undo those changes separately. Stopping the core does not automatically remove external interception rules.
Wait until a single device has been stable before distributing the side router’s gateway and DNS through DHCP. The gateway is usually DHCP option 3, and DNS is option 6; clients may need to renew their leases before the changes take effect. Once the side router becomes essential to the whole network, a shutdown or upgrade can affect every device. Keep a way to manage the main router and clear recovery steps.
The key is not to configure every setting at once, but to verify the core, explicit proxy, DNS, and forwarding separately. To learn about rules and subscriptions, start with the subscription import guide. For config fields, refer to the complete config reference. Avoid changing several layers at the same time.