Written for users who can already connect to a node and want mainland China sites to go direct. By the end you can lay out a correctly ordered rule list yourself — block rules first, LAN and mainland China domains direct in the middle, everything else falling through to the proxy — and you will know when each rule stops working and which step to check first when it does.
Two Dimensions of Split Tunneling: Domain and IP
A routing rule is basically a condition plus an outbound. Conditions come in four main kinds — domain, IP, port, and network type — while outbounds come in three: proxy, direct, and block. The usual split tunneling setup writes one set of rules for each of the two condition types: domains matching geosite:cn go direct, IPs matching geoip:cn go direct, and everything else goes to the proxy.
The decision happens inside the core, and the order is fixed. The destination is matched in whatever form it arrives in: if the application hands the core a domain, domain rules are compared first. Only when no domain rule matches does the core consult the domain strategy to decide whether to resolve an IP, and then compare that IP against the IP rules.
This order explains a very common symptom: a config with geoip:cn but no geosite:cn barely does anything when the domain strategy is AsIs — the core never resolves the domain, so there is no IP to compare, and every request falls through to the default outbound at the bottom of the list.
The reverse has its own limits: if the application resolves DNS itself and hands the core an IP address, domain rules have nothing to act on either. Accurate split tunneling starts with getting domains into the core as domains.
Match Order: Top to Bottom, First Hit Wins
The rule list is an ordered array, not a set. The core compares from the first entry down, stops at the first match, and ignores everything after it. Order is the logic: block rules before direct rules, direct rules before the catch-all.
In v2rayN, Settings → Routing Settings is where this array lives, and the Proxy, Direct, and Block entries in the outbound dropdown map to the proxy, direct, and block outbound tags in the core config. Each row describes a single condition combination; you change the order by moving rows up and down.
An order that covers most situations looks like this. The last row is not a rule — it is the default outbound the core uses when nothing matches.
| Order | Condition | Outbound | Effect |
|---|---|---|---|
| 1 | geosite:category-ads-all | Block | Ad and analytics domains rejected outright |
| 2 | geosite:private | Direct | LAN domains bypass the proxy |
| 3 | geoip:private | Direct | Address ranges such as 192.168.0.0/16 go direct |
| 4 | geosite:cn | Direct | Mainland China sites matched by domain |
| 5 | geoip:cn | Direct | Catch-all for mainland China IPs not covered by domain rules |
| 6 | No rule matched | Proxy | Default outbound; all remaining traffic goes through the node |
Getting the order wrong has concrete costs. Put IP rules ahead of domain rules and, under the IPOnDemand strategy, every connection resolves the domain first — adding first-packet latency and risking a misjudgment when a CDN resolves to an IP outside mainland China. Put block rules last and ad domains get swallowed by an earlier direct or proxy rule, so the block rule is never reached.
Four Ways to Write Domain Rules
Domain conditions accept four prefixes, from broadest to narrowest. Using the wrong prefix is the most common cause of inaccurate split tunneling.
| Syntax | Matches | Example |
|---|---|---|
| Bare string / domain: | The domain and all of its subdomains | domain:qq.com matches www.qq.com |
| full: | The exact domain only | full:www.example.cn does not match a.www.example.cn |
| keyword: | The string appears anywhere in the domain | keyword:doubleclick matches any domain containing that string |
| regexp: | Regular expression | regexp:.*\.google\.com$ matches its subdomains |
Beyond prefixes, you can reference geosite collections directly: geosite:cn covers common mainland China domains, geosite:geolocation-cn is a broader tier, geosite:private holds LAN domains, and geosite:category-ads-all is the ad and analytics domain collection. Collection data ships bundled with the rule files, so newly registered domains lag behind — a frequent reason rules are in place yet traffic still leaks.
A single rule can carry several conditions separated by commas; matching any one of them counts as a match.
"domain": [
"domain:qq.com",
"full:www.example.cn",
"keyword:doubleclick",
"regexp:.*\\.google\\.com$",
"geosite:cn"
]
One caveat: keyword: and regexp: are Xray core extensions and do not work under the v2ray core. v2rayN lets you switch cores under Settings → Parameter Settings, v2rayNG always uses the Xray core, and v2flyNG uses the v2fly core; before moving rules between cores, confirm whether these two syntaxes are supported.
IP Rules and Where geoip:cn Actually Applies
geoip:cn judges where an IP is registered, not where a domain belongs. A mainland China domain that resolves to an overseas CDN IP is treated as non-China, while an overseas domain that resolves to an IP in mainland China is treated as China. IP rules therefore work well as a fallback, not as your primary criterion.
LAN addresses need an explicit direct rule. geoip:private covers ranges such as 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, and 127.0.0.0/8; with only geoip:cn in place, requests to your router admin page, NAS, or network printer get pushed through the proxy — the node works, but local services will not open.
The Domain Strategy Decides When Resolution Happens
AsIs never resolves domains, which leaves IP rules effectively dead. IPIfNonMatch resolves once, only after every domain rule has failed, then restarts matching from the first rule with the resolved IP in hand. IPOnDemand resolves the moment an IP rule is encountered. The default v2rayN template uses IPIfNonMatch; unless you genuinely need IP-level precision, do not switch it to IPOnDemand.
One more easily missed detail: the second pass under IPIfNonMatch restarts from the first rule with the IP attached. An IP rule sitting near the top of the list can hijack, on that second pass, a request that a domain rule should have caught. If the outbound tag in your logs does not match expectations, first work out which pass produced the match.
Conclusion: Domain Rules Set Precision, IP Rules Provide the Fallback
Put geosite:private and geosite:cn ahead of geoip:cn, then use geoip:private to catch LAN traffic, and the remaining error in mainland China split tunneling comes down to two sources: CDN and DNS. Neither can be fixed by reordering rules — that takes tightening up your DNS configuration.
A Ready-to-Edit Rule Skeleton and How to Apply It
Putting the earlier conclusions together gives a complete ordered skeleton: block ad and analytics domains, send LAN traffic direct, send mainland China domains direct, send mainland China IPs direct, and route everything else through the proxy. You can copy it straight into v2rayN's routing settings or import it as a custom rule set.
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{ "type": "field", "domain": ["geosite:category-ads-all"], "outboundTag": "block" },
{ "type": "field", "domain": ["geosite:private"], "outboundTag": "direct" },
{ "type": "field", "ip": ["geoip:private"], "outboundTag": "direct" },
{ "type": "field", "domain": ["geosite:cn"], "outboundTag": "direct" },
{ "type": "field", "ip": ["geoip:cn"], "outboundTag": "direct" }
]
}
Direct group
- Domain
- geosite:cn, geosite:private
- IP
- geoip:cn, geoip:private
- Outbound
- direct
- Position
- After the block rules
Domain conditions first, IP conditions after; mainland China sites are judged by domain wherever possible.
Proxy group
- Domain
- geosite:geolocation-!cn
- Outbound
- proxy
- Position
- End of the rule list
- Fallback
- Default outbound when nothing matches
This one is optional — the default outbound covers it — but writing it out makes it easier to add exceptions later.
Here is how to apply it in v2rayN.
- Open the v2rayN main window and go to Settings → Routing Settings; in 7.x, the same list lives under Settings → Parameter Settings → the Routing tab.
- Add the rules one by one, in order: enter
geosite:category-ads-all,geosite:private,geoip:private,geosite:cn, andgeoip:cnin the condition field, set each outbound to Block or Direct, and note the purpose in the remarks column. - Set Domain Strategy to IPIfNonMatch. Unless you need IP-level precision, avoid IPOnDemand — it forces an extra resolution on every connection.
- Save, then restart the core so the new configuration is written to config.json and takes effect.
- Using SOCKS port 10808 (HTTP port 10809), visit one mainland China site and one overseas site, then check the Logs tab to confirm the two requests carry the direct and proxy outbound tags respectively.
Do not judge verification by whether a page loads. A mainland China site opens through the proxy just as well; the outbound tag in the logs is what tells you: direct means it went direct, proxy means it went through the node. If a mainland China site shows proxy, the rules did not match — check the domain strategy first, then rule order, then DNS.
Common Problems and the Order to Troubleshoot Them
The four problems below cover most split tunneling failures. Always troubleshoot in this order: domain strategy first, rule order second, DNS last.
Mainland China sites still go through the proxy: pages load, but noticeably slower
Check the domain strategy first. Under AsIs the core never resolves domains, so IP rules such as geoip:cn never fire; switch to IPIfNonMatch, restart the core, and check the outbound tags in the logs again.
geosite:cn is added, but new domains still slip through
geosite collections are bundled data, so newly added domains lag behind. Add a direct rule for the missing domain with the domain: prefix, place it ahead of the catch-all, and test again.
Admin pages for LAN devices will not open
Add a direct rule for geoip:private and put it at the very top of the list. geoip:cn alone does not cover ranges such as 192.168.0.0/16, so those requests get sent to the node.
Nothing changes after saving the rules
v2rayN only regenerates the core configuration after you save the routing settings, and it takes a core restart to apply; while you are there, confirm the rule count in the logs matches what the interface shows.
After editing rules, do not stop at a single test. Try two or three mainland China sites and two or three overseas sites, then scan the outbound tags in the logs to confirm direct and proxy both appear where you expect — only then are the rules settled.