V2Ray Routing Rules: Split Traffic with geosite and geoip

Learn to route mainland China traffic directly and send other traffic through a proxy with real routing examples. Covers domainStrategy trade-offs and rule order.

At a Glance

This guide is for users who can already connect to a server and are ready to fine-tune traffic routing. It explains the difference between domain and IP lists, then combines direct routes for mainland China and LAN traffic with a default proxy route. The examples cover when IPIfNonMatch resolves a domain, how the first outbound acts as a fallback, and how to verify the selected route in client logs—so a page loading successfully isn't mistaken for proof that routing works as intended.

1. What geosite and geoip Match

geosite contains domain categories, while geoip contains IP address ranges. Neither is a service that automatically identifies website ownership or checks it in real time. Routing depends on the local data files, the destination information available to the core, and the order of the rules.

Rule typeMatchesLimitations
geosite:cnDomains in the cn category in the data fileThe core needs the domain; this does not include every site in Chinese
geoip:cnMainland China IP ranges in the data fileUses the destination IP; it doesn't identify the company behind a site
geoip:privateSpecial-use address ranges, including private and reserved addressesCommonly used for direct LAN access; exact ranges depend on the data file
domain:example.comA specified domain and its subdomainsManually add individual sites without relying on category labels
full:example.comExact domainDoesn't match www.example.com as well

Websites may use CDNs across multiple regions. The same domain can resolve to different addresses on different networks, so a domain matching cn and an IP matching cn are two separate checks. If the browser resolves a domain first and sends only the IP to the proxy, domain rules may not get a chance to match. Sniffing can recover domain information for some protocols, but it can't identify every request's domain.

2. Routing Example and Default Outbound

This is a complete routing object snippet, not a full configuration that can connect to a server on its own. Before merging it into an existing V2Ray or Xray configuration, check the outbound tags. Here, direct refers to a direct outbound using the freedom protocol, and proxy refers to a tested, working proxy outbound. Tags are just names; they don't create outbounds.

{
  "routing": {
    "domainStrategy": "IPIfNonMatch",
    "rules": [
      {
        "type": "field",
        "domain": [
          "full:localhost",
          "geosite:cn"
        ],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "ip": [
          "geoip:private",
          "geoip:cn"
        ],
        "outboundTag": "direct"
      }
    ]
  }
}

This snippet assumes the first entry in your existing outbounds array is a proxy outbound. In a standard routing setup like this one, traffic with no matching rule uses the first outbound—it isn't selected automatically by a tag named proxy. If the first outbound is actually direct, unmatched traffic to sites outside mainland China will also go direct. Don't copy a proxy outbound without server details just to satisfy the ordering requirement.

Here, “traffic to sites outside mainland China goes through the proxy” means that traffic not covered by the direct rules above uses the proxy by default. It is not a complete, real-time check of where a site is located. To force a specific domain through a particular outbound, add an explicit domain rule instead of relying on IP geolocation to always meet your needs.

Bottom line: Check the fallback before changing categories

Before saving, check the actual protocol and tag of outbounds[0] in the generated configuration. Once the default outbound is correct, test rule order with a domain exception. Even a carefully tuned category list can send unmatched traffic to the wrong outbound if the fallback is misconfigured.

3. Choosing domainStrategy and Avoiding Fallback Pitfalls

routing.domainStrategy controls whether the routing stage resolves a domain to match IP rules. It is not the same as choosing a DNS server or selecting an address for an outbound connection. If the same setting appears at different levels of a configuration, first confirm which object it belongs to.

IPIfNonMatch

Recommended

Try to match rules using the destination information already available. If nothing matches, resolve the domain and try matching again. This example uses that strategy and relies on the first outbound as a fallback, without adding an all-match rule at the end.

Best for: Setups that prioritize domain categories and also use mainland China IP ranges for direct routing.

AsIs

The routing stage doesn't resolve domains to IP addresses. Existing destination IPs can still match IP rules, but requests that arrive only as domains won't get geoip category results this way. The domain may still need to be resolved when the connection is made.

Best for: Setups that rely mainly on domain rules and aim to avoid extra DNS lookups during routing.

IPOnDemand

The domain may be resolved when the rules need an IP match. The earlier an IP rule appears, the sooner a lookup may occur; this doesn't mean every request is always resolved first.

Best for: Setups that need IP checks early in the rule flow and can tolerate the associated DNS lookups.

A common mistake is to add a proxy rule with network: "tcp,udp" at the end when using IPIfNonMatch. That rule can match a request in the first pass, so the “no rule matched” condition is no longer met. As a result, a domain outside geosite:cn may go straight to the proxy without a chance to match geoip:cn after resolution.

Routing-stage resolution also has privacy and connectivity trade-offs. Which DNS server receives a domain depends on the full dns configuration, the path DNS queries take, and how the browser resolves names. Changing domainStrategy alone doesn't guarantee that DNS queries use the proxy or prevent DNS poisoning.

4. Rule Order: Exceptions First, Categories Next

Rules are checked from top to bottom, and the first match determines the outbound. When a rule object includes multiple conditions, such as domain and ip, all of them must match. Multiple entries in the same domain array are alternatives. To route directly when either the domain or IP matches, split them into two rules as shown here.

For example, if a site is in the cn category but your tests require it to always use the proxy, insert the following object at the start of the rules array. example.com is a reserved example domain used to demonstrate the syntax; replace it with the domain you need to test.

{
  "type": "field",
  "domain": [
    "domain:example.com"
  ],
  "outboundTag": "proxy"
}

“Private IPs must always be matched first” isn't true for every setup. If a domain exception should take priority over its resolved IP address, preserve that order. If all private addresses must go direct, account for domain exceptions, DNS responses, and the resolution strategy. For corporate networks, confirm your address plan first; don't apply a public-network example over your existing policy without review.

5. Apply the Rules and Check the Active Configuration

v2rayN is a desktop client. v2rayNG uses the Xray core, while v2flyNG uses the v2fly core. The client interface generates or loads the configuration, but the selected core executes the rules. Full custom configurations and standard node-mode settings have different entry points and scopes. Don't change both and then guess which one took effect.

  1. Back up your current configuration

    Note the active server, routing profile, and local listening port, and save your current custom configuration. Confirm the server connects before changing routes.

  2. Open the routing settings

    In v2rayN, the usual path is Settings → Routing Settings; in v2rayNG, open the side menu and select Routing Settings. Names may vary between versions, so follow the current interface. Review the existing rules before making changes; don't delete the whole profile.

  3. Choose a configuration method

    In the visual rule editor, enter the domains, IPs, and target outbounds separately, then check the order. Merge the routing object in this guide only when using a full custom configuration. Don't paste an entire JSON object into a field that accepts only a list of domains.

  4. Check the actual tags

    Review the generated or loaded configuration. Confirm that both direct and proxy exist, and check the first outbound. The interface options “Direct” and “Proxy” may map to different tags, so use the names in the actual configuration.

  5. Restart and check the logs

    Save and activate the routing profile, then stop and restart the connection. Check the runtime logs for rule parsing errors, missing resource files, or unknown outbound tags. Saving the editor doesn't necessarily reload the running core.

When comparing core behavior, record the core and its version—not just the client version. v2rayNG and v2flyNG use different cores, not just different interfaces to the same core. Check extension fields and resource-loading behavior separately for each custom configuration. For details on basic fields, see the site's JSON Reference.

6. Verify Routing with Requests and Logs

First confirm that requests reach the core, then check that they use the expected outbound. Browser extensions, system proxy bypass lists, and terminal environment variables can all change the request path. The examples assume a SOCKS listener is active at 127.0.0.1:10808. Port 10808 is for demonstration; it isn't the default on every installation. Replace it with your active listening port before running the commands.

curl --proxy socks5h://127.0.0.1:10808 --connect-timeout 10 --max-time 20 -I https://www.baidu.com/
curl --proxy socks5h://127.0.0.1:10808 --connect-timeout 10 --max-time 20 -I https://example.com/

socks5h tells curl to send the domain to the proxy, which is useful for testing domain rules. It doesn't guarantee that DNS lookups go through the remote proxy. The first request tests the cn domain category; the second tests the fallback for a domain outside the direct-route categories. A successful HTTP response confirms that a connection was made, but check the access log's destination address and outbound tag to verify the actual route.

TestExpected resultCheck first if it fails
A domain listed in the data under cnLogs show the direct outboundgeosite data, whether the domain reached the core, earlier rules
An active device on your LANLogs show the direct outboundprivate data, IP rules, LAN connectivity
A domain outside the direct-route categoriesLogs show the proxy outboundFirst outbound, additional rules, resolved address
A domain with a manually configured proxy exceptionThe exception rule matches firstException placement; domain vs. full matching

To test a LAN address, use a device that actually exists on your network, such as a router at 192.168.1.1. That's just an example address. If the device doesn't serve web pages, a failed connection doesn't mean the routing rule is wrong. Logs show which outbound was selected; whether the destination service responds is a separate check.

Why do some mainland China sites still use the proxy with geoip:cn?

First check whether the request reaches the core as a domain or an IP, then review domainStrategy. With AsIs, domains aren't resolved for IP rule matching. With IPIfNonMatch, check whether an all-match rule at the end is catching the request first. Finally, confirm that the resolved IP is included in the cn data you're using.

Why does a mainland China domain resolve to an IP outside China?

A domain category doesn't guarantee the location of the server's IP address. If geosite:cn already matched and routed the request directly, a later geoip rule won't change the outbound. To make routing decisions by IP, adjust the strategy and rule order deliberately, then retest the CDN's resolved addresses.

Why do the logs still show the old outbound after I saved the rules?

Make sure the edited routing profile is the one that's active, then stop and restart the core. A full custom configuration may not use the routing editor's settings for standard node mode. Check the configuration actually loaded for this run, not just the editor.

All requests are going direct. What should I check first?

First check whether the first entry in outbounds is a direct outbound and whether an all-match rule appears earlier in the list. Then use the curl command above with an explicit SOCKS port to confirm that traffic reaches the core. If there are no matching access logs, troubleshoot the request path before adding more rules.

Download v2rayN / v2rayNG