First, separate traffic capture from proxy rules
If a website opens in your browser but terminal commands time out, first check whether the traffic is reaching the client—not whether you need a different node. System proxy and TUN are two ways traffic enters the client; rule mode and global mode determine where it goes next. These settings solve different problems.
System proxy registers a local proxy address in macOS network settings. An app sends requests through the proxy only if it reads and honors those settings. TUN creates a virtual network interface and uses routes to send covered IP packets to the core. mihomo is a proxy core compatible with the Clash configuration ecosystem; the client provides the interface, configuration management, and permission services.
| Comparison | System proxy | TUN mode |
|---|---|---|
| How traffic is captured | Apps read the proxy settings and connect to a local port | A virtual network interface and routes send IP packets to the core |
| Typical use cases | Browsers and desktop apps that honor system proxy settings | Apps that ignore system proxy settings, including some UDP apps |
| Terminal commands | Usually require proxy options or environment variables | Usually need no per-command setup when covered by routes |
| Permissions | Usually no TUN helper service required | Usually requires an authorized helper service to configure the interface and routes |
| DNS handling | Depends on the app and proxy protocol | Can use DNS hijacking and the core's DNS, but coverage is not unlimited |
System proxy: check settings and the local port
Confirm the proxy is set in macOS
On macOS 13 or later, open System Settings → Network → Wi-Fi → Details → Proxies. For a wired connection, check the active Ethernet service. After enabling system proxy in the client, check the address and port for Web Proxy, Secure Web Proxy, or SOCKS Proxy. The client determines which settings it writes.
The address is often 127.0.0.1, which means this Mac; the port must match the one the client is listening on. The commands below use 7890 as an example mixed port for HTTP and SOCKS. This is not the default for every client. Check the client's port settings before running the commands.
# Show the proxy settings currently reported by macOS
scutil --proxy
# Check whether a process is listening on the example TCP port
lsof -nP -iTCP:7890 -sTCP:LISTEN
- In
scutil --proxy, checkHTTPEnable,HTTPSEnable, orSOCKSEnable, along with the corresponding port. - If
lsofreturns no output, first check for a typo in the port, whether the core is running, and whether the port has been changed. - If the process listening on the port isn't the current client, check for a port conflict. Avoid running two clients that compete for the same address.
Enabling system proxy does not make every app switch over immediately. An app may use its own network stack, an existing long-lived connection, or separate proxy settings. After changing settings, make a new request and restart the app if needed, then check the client's connection log. Don't rely on the menu bar toggle alone to confirm that it worked.
Terminal commands: test the proxy with an explicit setting
Whether a command-line tool uses macOS system proxy settings depends on how the tool is implemented. Common curl workflows read proxy environment variables, but that doesn't mean curl automatically follows the settings in the system proxy panel. Test with an explicit option first to distinguish a proxy entry-point issue from a connection issue with the site.
Set an HTTP proxy first, then test SOCKS
# Send an HTTPS request through the local HTTP proxy; wait up to 15 seconds
curl --proxy http://127.0.0.1:7890 \
--connect-timeout 10 --max-time 15 -I https://example.com
# Use SOCKS5 and let the proxy resolve the destination hostname
curl --proxy socks5h://127.0.0.1:7890 \
--connect-timeout 10 --max-time 15 -I https://example.com
The second command works only if the port supports SOCKS. In socks5h, the h means the proxy resolves the destination hostname. With socks5, curl usually resolves it locally first. This difference matters when troubleshooting DNS.
Set temporary variables for repeated use
# Affects only this terminal session and child processes started from it
export http_proxy=http://127.0.0.1:7890
export https_proxy=http://127.0.0.1:7890
# Clear these after testing to avoid using them by mistake later
unset http_proxy https_proxy
Using http:// for https_proxy is not a contradiction: it describes the protocol used to reach the local proxy. HTTPS destinations usually connect through an HTTP CONNECT tunnel. TLS encryption between the app and the destination is not automatically disabled.
TUN mode: permissions, routes, and rule-based routing
TUN is a Layer 3 virtual network interface that handles IP packets. On macOS, a client typically uses a privileged helper service to create or manage the interface and configure routes. Before enabling it, select a valid configuration and make sure the core starts correctly. Then install the helper service and grant system permissions as prompted by the client. Never enter your macOS login password on a subscription page or in a configuration file.
Key settings in a minimal configuration
This mihomo configuration snippet explains common fields; it is not a complete subscription. Some clients generate these fields in the interface or override subscription values. Back up your configuration before editing, and check the effective configuration afterward. Don't overwrite an entire subscription with this snippet.
tun:
enable: true
stack: mixed
auto-route: true
auto-detect-interface: true
dns-hijack:
- any:53
dns:
enable: true
enhanced-mode: fake-ip
enableturns on TUN. It still requires sufficient system permissions and a successfully started core.stackselects the network stack implementation. This example usesmixed; that doesn't mean it is the best choice for every Mac or network.auto-routerequests automatic route configuration;auto-detect-interfacedetects the outbound interface. Check the egress interface again after switching between Wi-Fi, Ethernet, or a hotspot.dns-hijackspecifies which traffic to hijack.any:53targets traditional DNS requests on port 53 that enter the relevant handling path; it does not intercept all encrypted DNS.
This snippet alone is missing nodes, policy groups, rules, and a suitable upstream DNS, among other settings. Prefer configuration methods supported by your client. If the core reports an invalid field, first confirm the core type and version, then follow the documentation for that version.
TUN and global mode do different things
With TUN enabled, traffic enters mihomo and can still be matched against rules by domain, IP, or other criteria in rule mode. Traffic matching a direct rule goes directly; traffic matching a proxy group uses the selected egress in that group. Global mode usually sends traffic to the global policy group, but is still limited by capture coverage and excluded routes. Enable TUN to capture more traffic; check rules and policy groups to change where it goes.
DNS: a working website doesn't mean DNS took the same path
DNS translates domain names into IP addresses. System proxy changes how an app connects to a proxy; it does not control how every app resolves domain names. A browser might send the hostname through the proxy or use its own secure DNS. Other programs might query system DNS first and then connect to the resulting IP.
TUN can work with the core's DNS to handle more DNS requests. With fake IP enabled, the core assigns a virtual address to a domain and maps it to the real destination when a connection is made. An address in the 198.18.0.0/15 range is not necessarily a problem, but check the fake-IP range in your actual configuration.
Check DNS issues at three levels
- Check the system resolver. Run
scutil --dnsto see the current resolvers. This shows the system configuration, but doesn't prove that every app uses those resolvers. - Check the core's logs. Open the client's connections and logs, then make a new request to the same domain. Check for a DNS request, a matching rule, and the selected egress.
- Check the app's own settings. Look at the browser's Secure DNS settings, in-app proxy settings, and encrypted DNS options. DoH uses HTTPS; DoT typically uses port 853. Hijacking port 53 alone won't cover them.
Don't assume one dig command tells you how DNS works across the whole system. macOS split DNS, VPN resolvers, and app caches can all produce different results. The path used by dig also differs in some respects from apps that use the system resolver. When troubleshooting, note the domain, time, and tool used so you don't compare results from different tests.
Games and UDP: check the node after confirming traffic is captured
Games often use both TCP and UDP. Traditional HTTP system proxies generally can't handle UDP packets sent directly by a game. SOCKS has a UDP relay mechanism, but the app must explicitly support and use it. TUN can send more of this traffic to the core, making it a better option when troubleshooting game connections that ignore system proxy settings.
However, a virtual network interface can't add UDP support to a remote node. UDP may be limited by the node protocol, server configuration, selected policy-group egress, or local network. First check whether the game connection appears in the client's connection list. Then see whether it matched DIRECT or a proxy group, and finally confirm that the selected node supports the required traffic.
- Login works, but a match won't start: Check the TCP requests used during login and the UDP connections used in-game separately. Don't test only the login page.
- Connected, but lag is high: Compare in-game latency and packet loss on the same server and at the same time. An HTTP speed test in the node list is not a measure of game latency.
- LAN play or device discovery is failing: Check your LAN bypass rules. Broadcast, multicast, and discovery protocols should not be treated like ordinary remote unicast connections.
TUN is not guaranteed to work with apps that rely on a specific network interface, anti-cheat software, or a specialized transport. Keep your original network settings and a way to restore them. Change one setting at a time to find out whether the issue comes from traffic capture, rules, or the egress.
Choosing a setup and recovering from network issues on Mac
Choose the right traffic entry point for your apps
- Mostly use browsers and apps that honor system proxy settings: Start with system proxy. It's easier to configure and makes the local port easier to check.
- Use terminal commands occasionally: Add
--proxyto the command or set variables for the current session to keep the changes scoped. - Several apps ignore the proxy, or you need UDP support: Consider TUN, and check the helper service, DNS, and routes as well.
- Connected to a corporate VPN: Follow your organization's network requirements first. Both tools can change routes and DNS, so test them separately instead of enabling both at once.
If the network drops after enabling TUN, restore connectivity before troubleshooting
- Turn off TUN and leave the client running, then check whether the regular network connection returns. Don't import a series of different subscriptions yet.
- Turn off system proxy, clear proxy variables from the test terminal, then confirm that the connection is direct. If you set
all_proxyor its uppercase equivalent, clear that too. - Run
scutil --proxyto check for leftover proxy settings, androute -n get defaultto inspect the default route. TUN may use more specific split routes, so the default route alone does not show the full capture result. - Run
netstat -rn -f inetto view IPv4 routes. For IPv6, also runnetstat -rn -f inet6. Seeing autuninterface doesn't necessarily mean it's from the current client; another VPN may be using it. - Once connectivity is restored, test again with only one traffic entry point enabled. If only TUN fails, check helper service permissions, route conflicts, and DNS logs.
System proxy and TUN don't have a fixed ranking. System proxy works well with apps that actively use a proxy; TUN captures more traffic but adds routes, permissions, and DNS to troubleshoot. Start with the fewest settings that meet your needs, then expand coverage as needed. It's easier to maintain than enabling everything at once.