V2Ray Routing Rules: geosite and geoip Split Tunneling Guide

Set up split tunneling with geosite, geoip, and custom domain rules to route traffic in mainland China directly and other traffic through a proxy. Learn rule order, domainStrategy options, and how to troubleshoot common misconfigurations.

At a glance

This guide is for users who have already imported a node and want to route traffic by domain and IP address. It explains domain and IP lists, the default outbound, and rule order with a sample routing configuration. Then, you’ll apply the rules in v2rayN and verify them in the logs. The examples use the common Xray/V2Fly field-based routing syntax. Subscription node settings, client menus, and core configuration are treated as separate layers.

1. What geosite and geoip Match

Routing rules don’t change a node’s protocol. They select an outbound for each connection entering the core. VMess, VLESS, and other protocols determine how a proxy connection is established; routing rules decide whether a destination uses the proxy, a direct connection, or another configured outbound. Having a working node in your subscription doesn’t mean you already have a suitable routing policy.

geosite:cn refers to the cn category in the domain data file, while geoip:cn refers to the set of IP addresses in China in the IP data file. The first checks whether a domain appears in a list; the second checks whether a destination IP falls within a listed address range. Neither detects a website’s language, and neither guarantees that every service in mainland China, cross-border site, or CDN address will behave as you expect.

Domain rules

Field
domain
Example entry
geosite:cn
Exact domain
full:example.com
Domain and subdomains
domain:example.com

The core needs to know the domain. If a connection provides only a destination IP, a domain list alone cannot match it.

Address rules

Field
ip
Example entry
geoip:cn
Private addresses
geoip:private
Example CIDR ranges
192.168.0.0/16

Useful for connections made directly to an IP, or for matching an address after the domain is resolved during routing.

When specifying domains, use full: or domain: for clarity. A plain string may match as a substring and catch unrelated sites with similar names. By contrast, domain:example.com matches the domain and its subdomains, but not notexample.com. The example.com references in this guide illustrate syntax only; they are not connectivity test services.

2. Rule Order: Put Custom Exceptions Before Lists

Standard field rules are checked in array order. The first match determines the outbound; the router won’t automatically choose the rule that seems more specific. When a rule contains both domain and port, both fields generally need to match. Multiple entries in the same domain array are alternatives—any one can match. To match “this domain or this IP,” use two separate rules.

  1. Start with essential exceptions: For example, put business domains that must use the proxy first, so a later direct-connection list doesn’t catch them beforehand.
  2. Next, add domain lists: Send recognized domains in mainland China directly, avoiding extra DNS lookups for routing where possible.
  3. Then check addresses: Send private addresses and IPs in mainland China through the direct outbound to cover destinations accessed by IP.
  4. Handle unmatched connections last: This example uses the first outbound as the default rather than adding an unconditional catch-all rule.

Another common misconception is that “direct in mainland China, proxy elsewhere” accurately identifies where every company is based. In practice, this policy combines list matching with a default outbound: connections outside the mainland China lists use the proxy by default, but that doesn’t prove they’re located abroad. Handle cross-region deployments, corporate intranet domains, and services that require a fixed egress with explicit exceptions.

3. Choosing a domainStrategy Value

routing.domainStrategy controls how DNS resolution results are used for routing matches. It doesn’t directly choose which DNS service a browser uses, and it differs from the domain resolution policy of the direct outbound. When troubleshooting, first confirm which configuration object you’re editing; identical field names don’t guarantee identical behavior.

ValueBehavior during routingWhen to use it
AsIsDoesn’t resolve domains for routing; IP rules can still match when the destination is already an IP address.When domain rules are sufficient and you don’t need to resolve domains for additional IP matching.
IPIfNonMatchIf the first routing check finds no matching rule, the domain is then resolved and routing is tried again.Classify by domain first, then use the mainland China IP list if no domain rule matches.
IPOnDemandAttempts to resolve a domain as needed when a rule requires the destination IP.When you want IP checks to run earlier and accept the associated DNS dependency.

This example uses IPIfNonMatch. A domain matching geosite:cn is routed directly. If an unknown domain has no match on the first pass, its resolved IP may match geoip:cn. Results can differ if DNS lookup fails, the returned address isn’t in the target list, or an earlier rule has already matched.

Take extra care with rule order when using IPOnDemand: if an earlier IP rule matches based on the resolved address, later domain exceptions won’t be checked. Putting custom domain exceptions first is usually easier to maintain than continually adding address ranges afterward.

4. Routing Example: Direct in Mainland China, Proxy by Default Elsewhere

The snippet below shows only the top-level routing object; it isn’t a complete client configuration and can’t run on its own. The full configuration’s outbounds must define a proxy outbound tagged proxy and a direct outbound tagged direct, with proxy as the first outbound. The existing client configuration supplies the node address, authentication details, and inbound settings.

{
  "routing": {
    "domainStrategy": "IPIfNonMatch",
    "rules": [
      {
        "type": "field",
        "domain": [
          "full:example.com",
          "domain:example.net"
        ],
        "outboundTag": "proxy"
      },
      {
        "type": "field",
        "domain": [
          "geosite:cn"
        ],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "ip": [
          "geoip:private",
          "geoip:cn"
        ],
        "outboundTag": "direct"
      }
    ]
  }
}

With this traditional data format, the core also needs access to the corresponding geosite.dat and geoip.dat files. Missing files, incorrect paths, or nonexistent categories can cause errors while loading the configuration. Reload the core after updating the rule data. Before switching data sources, check that the categories you use are still available.

5. Apply and Verify the Rules in v2rayN

In standard node mode, v2rayN typically generates the core configuration, so edits to a temporary JSON file may be overwritten the next time it starts. Manage rules through Routing settings where possible; use the appropriate custom-configuration entry when you need a fully customized config. Button locations may vary between desktop versions. The steps below refer to an interface with a Settings → Routing settings entry.

  1. Back up the current rules

    Open Settings → Routing settings, save a copy of the existing rules, and note which routing profile is selected. Don’t delete the original profile yet—you’ll need it to roll back if testing fails.

  2. Organize the rule order

    Edit a test profile in Routing settings and add, in order, domain exceptions, mainland China domain rules, and IP rules. Enter each value in its corresponding field in the rule editor; don’t paste the entire top-level JSON into a single domain field.

  3. Check the resolution strategy

    Set the profile’s domain strategy to IPIfNonMatch and verify each rule’s outbound. If the interface doesn’t expose this field, inspect the generated configuration; don’t infer its value from the profile name.

  4. Select the profile and reload

    Save, select the routing profile you just edited, and then reload the core. Saving in the editor doesn’t necessarily activate the profile. Check the loaded configuration and logs to confirm what’s in use.

  5. Test each outbound

    Test destinations that should use a direct connection, the proxy, and your local network. Check the destination and outbound tag in the logs. Close existing connections before testing; long-lived connections won’t automatically switch outbounds when rules change.

Before verifying, make sure traffic is actually reaching the core. If an app doesn’t use the system proxy, even a complete routing setup can’t handle its traffic. The numbers below are example test settings, not defaults for every installation. Check the listening port in your client before running the command.

10808
Example local SOCKS port
443
Common HTTPS destination port
3 rules
Routing rules in this example
curl --proxy socks5h://127.0.0.1:10808 --head https://example.com/

Here, socks5h passes the destination domain to the proxy for resolution, which helps test domain rules. If the domain is resolved locally first, the core may see only an IP address, so the results aren’t directly comparable. The domain in this command matches the first rule in the example. Check for the proxy outbound tag rather than using whether the page loads as proof that routing worked.

6. System Proxy and TUN: Verify Based on How Traffic Is Captured

The same routing rules can behave differently depending on how traffic is captured. The node hasn’t changed; the destination information available to the core has. With a system proxy, an app may pass the domain directly. With TUN, a connection usually arrives as IP packets, and whether the domain can be recovered depends on settings such as DNS interception and sniffing.

Choose a verification method based on the destination information

System proxy
  • Confirm that the browser or app is using the proxy settings.
  • Test with an explicit SOCKS proxy to reduce interference from system settings.
  • Check domain rules first, then verify address matching for anything that didn’t match.
TUN mode
  • Confirm which core and configuration format are handling the traffic.
  • Check whether the logs show a domain or an IP address only.
  • Check DNS interception and local network access before adjusting the rules.

First confirm which core is handling the traffic, then use the corresponding rule format. Don’t apply this JSON directly to every TUN configuration.

Desktop v2rayN, Android v2rayNG, and v2flyNG can use similar routing goals, but their menus, tags, and import formats aren’t necessarily identical. v2rayNG focuses on the Xray core, while v2flyNG uses the V2Fly core. When migrating rules, check which fields and data formats the current core supports. Node subscriptions may not include client-side routing settings.

7. Common Misconfigurations: Narrow Down the Cause with Logs

Added geosite:cn, but sites in mainland China still use the proxy?

First check whether the log shows a domain or just an IP, then confirm that the domain is actually in the cn category in the data file you’re using. If you see only an IP, check geoip:cn and the resolution strategy. If a business domain isn’t in the list, add an explicit direct-connection rule with domain:. Don’t simply route every unknown destination directly.

Set IPIfNonMatch, but geoip still isn’t working?

Check whether a wildcard rule such as port: "0-65535" is matching first. Remove any catch-all rule from the test profile, confirm the first outbound is the proxy, and test a destination that doesn’t match a domain rule. Also check that the DNS used for routing can resolve the domain successfully.

All connections fail after saving the rules. What should I do?

Switch back to the backup profile first, then check the core startup logs. If the data files can’t be read, fix their paths or update the files. If the error mentions an outbound tag, check outboundTag character by character. Don’t change your subscription or node before resolving a configuration loading error.

The same website sometimes connects directly and sometimes through the proxy. How do I find out why?

Record the main domain, static asset domains, and destination IPs separately. Check whether they use different address families or CDN addresses. Close existing connections and test again. If domain-based and IP-based connections produce different results, standardize the test path first, then decide whether to add domain exceptions.

Change one variable at a time: confirm traffic capture, check that the configuration loads, verify which rule matches, then investigate DNS and the actual connection. Temporarily increasing log detail can help, but remove subscription URLs, authentication details, and other sensitive information before sharing logs. For more configuration fields, see the Configuration Reference. For connection-level issues, work through the Troubleshooting Guide.

Download the client