V2Ray Routing Rules in Practice: Split Routing for Direct Access in Mainland China and Proxy Access Abroad

Learn how to configure routing rules by domain, IP, and geosite/geoip data for direct access to mainland Chinese sites and proxy access to sites abroad, with rule-ordering and troubleshooting tips.

At a glance

This guide is for users who have imported a subscription and can connect to nodes normally, but want to avoid routing mainland Chinese sites through a proxy. It explains request matching, provides routing snippets that can be merged into an existing configuration, and covers v2rayN settings, rule order, DNS behavior, log troubleshooting, and verification.

The core of split routing: choose an outbound for each request

V2Ray routing is not another proxy protocol. It is a set of conditions the core uses while processing requests. After an application request enters through a local SOCKS, HTTP, or transparent proxy inbound, the core reads the destination domain, IP, port, and network type, then checks routing.rules from top to bottom. The first matching rule determines the outboundTag; subsequent rules are skipped.

A typical configuration defines three outbound tags: proxy connects to a subscribed node, direct accesses the destination directly, and block rejects the connection. Routing rules do not store node addresses or change VMess, VLESS, or other node parameters; they only send traffic to an existing outbound. After exporting a client configuration, confirm the actual tag names before copying these rules.

Application sends a requestInbound receives trafficIdentify domain and IPMatch rules in orderSelect outbound

“Direct for mainland China, proxy everything else” is usually implemented in three layers: send private addresses direct, send mainland Chinese domains and IPs direct, and send remaining TCP and UDP requests through the proxy. The last rule is the catch-all and must be placed at the bottom. If the proxy fallback comes first, every request matches immediately, so the later direct rules never take effect.

10808
Example SOCKS listening port
10809
Example HTTP listening port
6
Number of basic routing rules
7.12.7
v2rayN baseline used in this guide

Routing configuration: geosite, geoip, and the fallback rule

geosite contains domain-category data, while geoip contains categorized IP ranges. A domain request can first be checked against geosite:cn. If no domain rule matches, setting domainStrategy to IPIfNonMatch makes the core resolve the destination and pass it to the IP rules. This approach handles both domain-based access and applications that connect directly to an IP.

Direct access for private networks

Match
geoip:private
Outbound
direct
Typical targets
LAN and loopback addresses

Keeps router admin pages, network storage, and local services out of the proxy.

Direct access for mainland Chinese domains

Match
geosite:cn
Outbound
direct
Matching basis
Domain-category data

When the domain is still available, matching it first is usually more direct than resolving it and checking the result afterward.

Direct access for mainland Chinese IPs

Match
geoip:cn
Outbound
direct
Applicable requests
Direct IP connections

Also provides a fallback check using the resolved address when no domain rule matches.

Proxy all remaining traffic

Network
tcp,udp
Outbound
proxy
Position
End of the rule list

Acts as the final fallback and must not appear before any precise matching rule.

The snippet below contains only the routing object. Merge it into an existing complete configuration rather than launching it as a standalone configuration file. The ad-blocking rule requires a block outbound. If your current configuration has no such outbound, remove the first rule and keep the direct and proxy split-routing rules.

{
  "routing": {
    "domainStrategy": "IPIfNonMatch",
    "domainMatcher": "hybrid",
    "rules": [
      {
        "type": "field",
        "domain": [
          "geosite:category-ads-all"
        ],
        "outboundTag": "block"
      },
      {
        "type": "field",
        "ip": [
          "geoip:private"
        ],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "domain": [
          "geosite:cn"
        ],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "ip": [
          "geoip:cn"
        ],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "network": "tcp,udp",
        "outboundTag": "proxy"
      }
    ]
  }
}

domainMatcher: hybrid enables hybrid domain-rule matching. If an older core does not recognize this field, remove the line and use the default matcher. Classification data must also match the core version. If the logs say a dataset is missing while the configuration spelling is correct, update the core and rule data used by the client instead of treating the error as a failed node.

Putting it into practice in v2rayN: from subscription to custom routing

v2rayN stores subscriptions, selects the active node, and generates the core configuration. When routing is managed through the GUI, the client combines node outbounds and rule sets before starting the core. This is more reliable than repeatedly editing a temporary config.json, which may be regenerated after switching nodes, updating a subscription, or restarting the client.

  1. Confirm node connectivity.Update the subscription and select a node, then use “Test Server Real Connection Latency” to confirm that a connection can be established. Routing only assigns traffic; it cannot fix a node address, port, or authentication parameter.
  2. Open routing settings.In v2rayN 7.12.7, go to “Settings” → “Routing Settings,” create a rule set, and make it the active routing configuration. Button locations may vary between minor releases, but the routing entry name remains the same.
  3. Add precise rules.Create rules in order for ad blocking, private IP direct access, mainland Chinese domain direct access, and mainland Chinese IP direct access. For the outbound tag, select the existing block, direct, or proxy tag; do not enter a node remark.
  4. Add the final proxy rule.Set the network types to TCP and UDP, choose proxy as the outbound, and move the rule to the bottom. Without a final fallback, unmatched requests follow the core’s default behavior, which is less transparent.
  5. Save and restart the core.After saving the rules, restart the service once, then open the log window to confirm that the configuration loaded successfully. Closing the settings window without restarting may leave the running core on the old configuration.

v2rayNG and v2flyNG also provide routing settings, but they use different core lines. v2rayNG is commonly paired with the Xray core, while v2flyNG corresponds to the V2Fly core. The basic logic for field, domain, ip, network, and outboundTag is consistent, but available extension fields may differ. When moving between clients, keep the basic rules first and verify core-specific features one by one.

Rule priority: put specific conditions first and broad conditions last

Routing rules use a top-down first-match mechanism; they are not merged and recalculated to find the best result. If a domain belongs to both a custom proxy list and geosite:cn, its route depends on which rule appears first. A practical order is “manual exceptions, special categories, private addresses, regional categories, final fallback.”

Recommended order Example rule Outbound Why it goes here
1 Force specific domains through the proxy proxy Override later regional-category matches
2 category-ads-all block Handle explicit block targets first
3 geoip:private direct Keep local and LAN access direct
4 geosite:cn direct Identify mainland Chinese sites by domain
5 geoip:cn direct Add IP-range matching as a fallback
6 tcp,udp proxy Catch all remaining requests

To keep a domain on the proxy, place the custom rule before geosite:cn. Domain match types also differ: full: matches only the complete hostname, domain: matches the domain and its subdomains, and regexp: uses a regular expression. For ordinary split routing, prefer full or domain; use regular expressions only when pattern matching is genuinely needed.

{
  "type": "field",
  "domain": [
    "full:status.example.net",
    "domain:service.example.net"
  ],
  "outboundTag": "proxy"
}

Conclusion: exception rules must come before regional rules

When a site consistently uses the wrong outbound, adjust that site’s rule position before changing nodes. With first-match routing, ordering matters more than the number of rules.

Conversely, if a download site must always connect directly, create a separate direct rule and place it before the final proxy rule. Do not delete the entire geosite or geoip rule group for one exception, or a local issue will become a global routing change.

DNS and domain detection: why correct rules can still route incorrectly

Whether routing can match by domain depends on whether the core receives the original destination domain. When a browser passes the domain through local SOCKS5, the core can match geosite directly. If the upstream provides only an already-resolved IP, domain rules cannot participate and routing must rely on geoip. In transparent proxy scenarios, traffic sniffing may recover an HTTP hostname or TLS Server Name.

Which outbound handles DNS queries is a separate question. If system DNS resolves mainland Chinese domains normally while the proxy node connects to other destinations, basic split routing is usually sufficient. If you see DNS poisoning, different domestic and overseas results, or UDP query timeouts, configure the core’s DNS further and specify the DNS server addresses, query-domain scope, and outbound for DNS traffic.

Using IPIfNonMatch does not mean every domain is resolved first. Requests that already match geosite:cn or a custom domain rule can select an outbound immediately. Resolution is needed only when domain conditions produce no result and IP rules remain to be checked. That is why it is better suited to ordinary configurations than unconditional IP-based matching.

Log troubleshooting: from configuration loading to rule matches

When split routing fails, first distinguish between “the core did not start” and “the core started but chose the wrong outbound.” The former usually appears as an error or failed message within seconds of startup. Common causes include JSON comma errors, fields at the wrong level, missing outbound tags, and missing rule-data files. For the latter, raise the log level and inspect the destination and final outbound.

  1. Check the JSON structure.routing should sit at the configuration root alongside inbounds and outbounds. Extra commas and duplicated braces are common mistakes when copying snippets.
  2. Verify tag spelling.outboundTag is matched by its exact string value and must exactly match a tag in the outbounds array. A proxy node remark cannot substitute for an outbound tag.
  3. Check rule data.If the log says a geosite or geoip entry cannot be loaded, confirm that the data file exists and that the current core supports the category name.
  4. Temporarily raise the log level.Change loglevel from warning to info, restart the core, visit one mainland Chinese domain and one domain that requires the proxy, then inspect the connection records. Restore warning afterward to reduce routine log volume.
  5. Reduce the rule set.Keep only the three basic groups first: private, cn, and the final proxy rule. Once basic split routing works, restore ad categories, custom domains, and port rules one at a time.
{
  "log": {
    "loglevel": "info"
  }
}

If mainland Chinese domains still use the proxy, first check whether the final proxy rule appears before the geosite rule, then confirm whether the request carries only an IP. If it contains only an IP, check whether geoip:cn loaded successfully. If an overseas service goes direct, check whether it was incorrectly matched by a custom direct rule or regional data, and use the logs to confirm the actual destination domain.

When UDP requests fail, confirm that the current node protocol and transport settings allow UDP, and check that the final fallback rule’s network includes udp. Writing only tcp may leave web browsing mostly normal while DNS, real-time communications, or some network checks that depend on UDP time out. Allowing UDP in routing does not guarantee that the node accepts it; both ends must support it.

Conclusion: prove the rule match before judging node quality

When the same request switches between direct and proxy, outboundTag in the logs is the clearest indicator. Only after confirming that the request reached the expected outbound should latency, timeouts, and throughput be investigated as node or link issues.

Verify the result: run regression tests against a fixed target set

After saving the rules, do not test just one webpage. Browser cache, connection reuse, and DNS cache can preserve old results. Restart the core, close existing connections, and use a fixed checklist covering a LAN address, a mainland Chinese domain, a direct IP, an overseas domain, TCP, and UDP. Repeat the same checklist after every rule change so the results remain comparable.

A maintainable baseline usually needs only a few rules: private addresses direct, mainland Chinese domains direct, mainland Chinese IPs direct, explicit exceptions, and a final proxy fallback. The more rules you add, the harder overlapping categories and ordering conflicts become to troubleshoot. Before adding a rule, state the exact problem it solves and record which existing rule it must precede.

geosite and geoip data change as network resources are updated, so regional categories cannot permanently cover every domain and address range. For a small number of misroutes, add precise exceptions above the regional rules. Only when many targets fail at once should you inspect rule-data versions, core compatibility, and the DNS path.

Conclusion: keep the basic rules short and exceptions precise

A core set of six or fewer rules with a small number of full or domain exceptions is usually easier to verify and maintain after subscription updates than a large stack of broad regular expressions.

Download v2rayN