Deployment basics: running the core, routing traffic, and setting device gateways

Starting mihomo on OpenWrt only means that a proxy core process is running on the router. To route phones, TVs, and computers through it, you also need to handle traffic entry points, routing, and DNS. A loaded configuration or accessible dashboard alone does not prove that LAN traffic is being intercepted.

mihomo uses the Clash Meta configuration system and handles proxy protocols, rule matching, and connections. OpenWrt manages interfaces, routing, the firewall, and services. LuCI plugins can provide a graphical interface for these tasks, but the plugin, core, and subscription configuration remain separate components with separate update cycles.

  • Explicit proxy: Enter the proxy server address and port on a device or in an app. This is useful for validating a configuration first, but apps that ignore proxy settings will not automatically use the core.
  • Transparent proxy: The router uses firewall rules and policy routing to intercept traffic passing through it, so you generally do not need to configure an HTTP proxy on every device.
  • TUN: The core handles IP traffic through a virtual network interface. System routing, firewall forwarding, and loop prevention must still work together.

Main router or secondary router: map the actual traffic path first

Deploying on the main router

The main router provides the internet gateway, and LAN devices usually use it as their default gateway. Traffic naturally passes through this device, making transparent interception easier to centralize. However, a core restart, rule reload, or DNS misconfiguration can have a wider impact. Keep exceptions for direct internet access and the management address rather than intercepting every connection at once.

Deploying a secondary router on the same subnet

These example addresses illustrate a topology; they are not field measurements: the main router is 192.168.10.1, the secondary router is 192.168.10.2, and the test computer is 192.168.10.100/24. The secondary router's upstream default route points to the main router, while the test computer's default gateway points to the secondary router.

DeviceExample settingsWhat to verify
Main router192.168.10.1Provides the upstream gateway; keep its existing DHCP service initially
Secondary router192.168.10.2/24Upstream gateway is 192.168.10.1; required forwarding is allowed
Test computer192.168.10.100/24Default gateway is 192.168.10.2; DNS points to the configured resolver

When the secondary router and clients share a subnet, return traffic for direct connections may go straight from the main router to the client, creating an asymmetric path. Whether to use source NAT and how to handle ICMP redirects depends on connection tracking and the actual routing table; “enable NAT” is not a universal fix. A secondary router with two network interfaces and its own downstream subnet behaves more like a conventional router, usually with a clearer traffic path.

  • Changing a device's DNS to the secondary router does not also route its application traffic through that router.
  • DHCP options 3 and 6 typically specify the IPv4 gateway and DNS server. Clients need to renew their leases after you change them.
  • Do not start a second DHCP server on the same broadcast domain without a plan; devices could receive different gateways.
  • IPv6 default routes usually come from router advertisements. Changing the IPv4 gateway alone does not change the IPv6 path.

Check the platform and system: choose a compatible mihomo binary

Before downloading, check the OpenWrt version, CPU architecture, and available storage. Common official OpenWrt 23.05 and 24.10 images use firewall4 and nftables; third-party firmware may differ, so inspect the actual system instead of choosing a script by firmware name alone.

ubus call system board
uname -m
opkg print-architecture
df -h /overlay /tmp
free -m
command -v fw4
command -v nft
test -c /dev/net/tun && echo "TUN device available"

The opkg command above applies to firmware that uses opkg. If your system uses another package manager, follow the firmware documentation. uname -m reports the architecture of the running environment; it does not replace checking the CPU instruction set and release asset notes.

  • x86_64: This corresponds to the amd64 family, but optimized builds may require specific CPU instructions. Check the asset requirements on older x86 routers.
  • aarch64: This usually corresponds to arm64. If the hardware supports 64-bit operation but the firmware runs in a 32-bit environment, use the system's actual architecture.
  • ARM and MIPS: Check the ARM generation and floating-point requirements, as well as MIPS endianness. The chip family in a product listing is not enough.
  • Storage and memory: The core, rule sets, and geolocation databases all take up space. /tmp is usually in memory, so its contents do not persist after a reboot.

For Exec format error, check the architecture first. For Illegal instruction, verify the instruction-set requirements. If a file exists but will not run, the loader or file permissions may also be at fault; do not assume the subscription is invalid.

Deployment options: LuCI plugin, standalone process, or container

Option 1: Manage everything through a LuCI plugin

This suits setups that need subscription updates, startup integration, and coordinated transparent proxy rules. Choose a plugin that explicitly supports your OpenWrt firewall stack and mihomo, and read the documentation for that version. Plugin menus, override mechanisms, and core update channels vary; do not apply one plugin's setup steps to another.

Plugins usually generate the final configuration at runtime. Manually editing a generated file may not survive the next subscription update or service restart. Use the plugin's persistent override mechanism, and avoid starting a second standalone core that could compete for the same ports.

Option 2: Standalone binary and procd service

This suits users who want direct control over runtime options and firewall rules. For these examples, the core is at /usr/bin/mihomo and the data directory is /etc/mihomo; these are example paths, not defaults for every plugin. Install a reviewed configuration, then run the core in the foreground to inspect errors.

/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

Use -t to test the configuration. Even if the test succeeds, verify DNS, the outbound connection, and forwarding. Once foreground operation is stable, create a procd service under /etc/init.d/ and configure its startup command, standard output, failure recovery, and shutdown cleanup. Repeatedly launching background commands is no substitute for service management and can leave duplicate processes and stale rules behind.

Option 3: Run in a container

Containers can suit routers that already have a container management setup, but add network namespaces, data volumes, and permission boundaries. TUN requires the container to access the relevant device and have the necessary network administration capabilities. For transparent proxying, decide whether rules belong on the host or inside the container. Mapping only port 7890 generally provides an explicit proxy; it does not automatically intercept the entire LAN.

Transparent proxy and TUN: choose one traffic interception setup

Transparent proxying is the goal; TUN is one way to implement it. Other common approaches include REDIRECT and TPROXY. REDIRECT is often used to redirect TCP traffic; TPROXY can handle TCP and UDP, but requires policy routing, packet marks, and the corresponding kernel modules. Choose based on plugin support, firmware components, and network topology.

Traffic entry methodSystem requirementsWhat to check
Explicit HTTP / SOCKS proxyConfigure the proxy address in each appCheck for apps that bypass the proxy; verify UDP support separately
REDIRECT / TPROXYFirewall rules; configure policy routing as neededTCP and UDP interception scope, mark conflicts, and loop prevention
TUNTUN device, routes, and forwarding rulesWas the interface created? Does traffic reach it? Is DNS being overridden?

Before using TUN, check under LuCI's System → Software that kmod-tun is installed for the running kernel, and verify that /dev/net/tun exists. Do not install a module built for a different firmware kernel version. The device file only confirms a basic prerequisite; it does not mean routing is configured correctly.

  • Decide who manages routing: if the plugin generates interception rules, do not also copy a separate configuration that enables automatic routing.
  • Exclude the core's own proxy connections, the router's management address, the upstream gateway, and any required LAN subnets to prevent traffic from looping back into the core.
  • Check zones and forwarding under LuCI's Network → Firewall. Do not use a blanket allow rule to hide a ruleset problem.
  • For troubleshooting, temporarily disable software or hardware flow offloading and test again; offloading can change how subsequent packets are handled.

DNS routing: listener ports, upstream resolvers, and Fake-IP

OpenWrt commonly uses dnsmasq to provide DNS on the LAN. One easy-to-follow setup is for clients to send queries to the router's 53 port, then for dnsmasq to forward queries that need the core to 127.0.0.1:1053. This preserves dnsmasq's local hostname handling, but make sure the core's queries are not forwarded back to dnsmasq in a loop.

The snippet below shows only mihomo DNS settings, not a complete, working router configuration. It uses a conventional upstream to illustrate the port relationship. For a real deployment, choose upstream resolvers based on network reachability, privacy requirements, and how proxy server hostnames are resolved.

dns:
  enable: true
  listen: 127.0.0.1:1053
  enhanced-mode: fake-ip
  fake-ip-range: 198.18.0.1/16
  nameserver:
    - 223.5.5.5
    - 119.29.29.29
  1. Choose a single listener for port 53. If dnsmasq already listens on port 53 for the LAN, mihomo must not bind to the same address and port.
  2. Configure forwarding. Under LuCI's Network → DHCP/DNS, DNS forwarding can use the dnsmasq address format 127.0.0.1#1053. Also check whether dnsmasq still uses upstream DNS servers advertised by the upstream network.
  3. Prevent loops. mihomo's upstream resolver must not point back to this dnsmasq entry point. Proxy server hostnames also need a working initial resolution path.
  4. Cover the queries that actually occur. Traditional DNS uses both UDP and TCP on port 53. In-app DoH uses HTTPS, so redirecting port 53 will not automatically route it through the same DNS chain.

Fake-IP returns a mapped address that the core associates with a domain name. If a client receives an address in 198.18.0.0/16 but sends the connection through a gateway that does not intercept that range, DNS can return a result while websites remain unreachable. Test Fake-IP, DNS settings, and the traffic entry point together.

Test printers, screen casting, and apps that rely on LAN hostname discovery separately. If needed, use precise Fake-IP filters and local DNS rules. Check IPv6 DNS advertisements, AAAA responses, and outbound routing together; a successful IPv4 test does not prove that all connections are being intercepted. For more details, see the DNS section of the full guide and the Fake-IP glossary entry.

Validation sequence: from configuration tests to real LAN connections

Use a fixed sequence to isolate problems instead of changing firewall rules, DNS, and routing all at once. The following ports are examples for this article: explicit mixed proxy, 7890; core DNS, 1053; and, if enabled, a control interface restricted to 127.0.0.1:9090.

  1. Core: Test the configuration and check the logs. For a standalone procd service, use logread to inspect startup errors; for a plugin, start with its log page.
  2. Listeners: If ss is installed, run ss -lntup. Otherwise, use an equivalent tool provided by the firmware to verify the listening addresses and protocols for ports such as 7890 and 1053.
  3. Explicit proxy: Once LAN access is enabled and the firewall restricts allowed sources, have the test computer request a webpage through the secondary router's port 7890. This confirms the subscription and outbound connection work before you test interception.
  4. DNS: Send a query from the test computer to the intended DNS entry point. Check the core logs and response to distinguish a timeout, a valid mapping, and an upstream loop.
  5. Routing: Turn off the test computer's explicit proxy, leaving only the test gateway and DNS settings, and check whether connections still reach the core. On the router, also inspect ip route show, ip rule show, and the relevant routing tables.
  6. Protocols: Test regular websites, video, UDP apps, and IPv6 connections separately. A successful TCP test does not mean UDP or IPv6 follows the same path.

To test an explicit proxy from a client, install curl on that client and make sure the secondary router has the LAN proxy entry point open as described above. The example URL is only a test target; it is not guaranteed to match a proxy rule.

curl --proxy http://192.168.10.2:7890 --connect-timeout 10 -I https://example.com/
nslookup example.com 192.168.10.2

Do not judge success by whether your public IP changes: in rule mode, some destinations are meant to connect directly. Check connection logs for the destination, matched rule, policy group, and final outbound route. There is no universal speed benchmark for a router; encryption, single-core performance, MTU, connection quality, and log volume all affect throughput. Compare direct and proxied connections on the same device and to the same destination.

Long-term operation: updates, access controls, and recovery

  • Configuration updates: After updating a subscription, check syntax and resource loading before replacing the active configuration. Keep the last known working copy, and put persistent changes in plugin overrides or separately maintained files.
  • Core updates: Check that the new core supports your current fields, rules, and startup options, then test the configuration again. Refreshing a subscription does not update the program.
  • Admin interface: Bind the control interface to a loopback address when possible. If LAN access is necessary, set credentials and restrict access by source; never expose proxy or control ports on the WAN.
  • Storage: Avoid writing large amounts of debug logs to flash for extended periods. Plan for failed downloads and available space when updating rule resources, and do not keep your only configuration in a temporary directory.
  • Shutdown cleanup: When stopping the service, remove the interception rules, routes, and DNS forwarding it created. Otherwise, traffic may continue to be sent to a dead entry point after the process exits.

To roll back, first restore the test device's original gateway and DNS settings, then remove interception on the secondary router. For a main-router deployment, use the service stop and rule restoration steps prepared in advance. Keeping a wired local management connection available is more reliable than depending on a remote connection that may fail during an outage.

If you only need one computer to use a subscription, validate the setup with a desktop client first and consider router-level interception later. The main challenge in router deployment is not copying the core binary; it is keeping traffic routing, DNS resolution, the proxy outbound path, and the return path consistent.