Split Tunneling Setup

Set up v2rayN routing rules to send mainland China sites direct, proxy other traffic, and block ad domains. Learn how rule order and domain strategy affect routing.

At a glance

This guide is for users who have imported a server and confirmed the proxy works, but have not yet organized their routing rules. It covers the Xray core in the desktop version of v2rayN, with three outbound tags and six basic rules. You’ll check the system proxy entry point, rule order, and domain resolution settings. The example uses a conservative policy: route the mainland China domain category directly and proxy everything else. Ad domains get a separate rule at the top, which you can disable on its own if it blocks something by mistake.

1. Check where traffic enters

Split tunneling does not automatically identify a site as domestic or international based on the URL shown in your browser. The core matches rules against the destination domain, IP address, port, and other details it receives. If a request does not enter v2rayN through a local inbound, its routing rules won’t apply. The system proxy generally affects only apps that honor the system proxy settings. Apps that connect directly need their own proxy settings or can be routed through Tun separately.

App requestLocal inboundRule matchingOutbound selectionDestination

This guide follows the settings layout in the v2rayN 7.x desktop interface. Start by testing with the system proxy; do not enable Tun at the same time. Button locations may vary between minor versions. Go to Settings → Parameters to check the local listening port, and Settings → Routing to manage rule sets. If the client is using a different core, switch to Xray and confirm the server still connects before applying the Xray examples below.

  1. Select a server you’ve confirmed works and set it as the active server. This rules out a connection problem with the server itself.
  2. Note the actual port for the local HTTP or mixed inbound. Don’t use a SOCKS-only port as the HTTP proxy port.
  3. From the tray menu, choose System Proxy → Set system proxy automatically. Make sure no browser extension is overriding the system proxy.
  4. Back up the current routing rule set and make a copy for testing. Temporarily close other proxy apps to prevent them from changing the traffic entry point.
3 types
Direct, proxy, and block outbounds
6 rules
Basic rules in this guide
10808
Example port used in the test command

The 10808 port shown here is just an example for the command below. You don’t need to change your port to this value, and it isn’t the default for every installation. Use the command as written only if Parameters shows that this port accepts HTTP or mixed proxy requests.

2. Set up direct, proxy, and block outbounds

v2rayN combines the active server and interface settings to build the core configuration. In a rule’s outbound option, you can usually select direct, proxy, or block. These are tags in the generated configuration, not protocol names. VMess and VLESS servers can both be used as proxy outbounds, so there’s no need to rewrite the routing rules in a different syntax.

Connection outbounds

Direct tag
direct
Proxy tag
proxy
Proxy destination
Current active server
Use case
Direct for mainland China domains; proxy all other requests

Direct traffic still uses your local network to reach the destination. Matching a direct route does not guarantee that the destination is reachable.

Blocking and fallback

Block tag
block
Blocked category
geosite:category-ads-all
Fallback outbound
proxy
Fallback networks
tcp,udp

Blocking applies only to matching requests; it can’t identify every ad in a webpage.

In Settings → Routing, create a test rule set. For each rule, specify the domain, IP, network, and outbound tag as needed. After saving, set this rule set as the active one; editing it without switching the active rule set won’t change how requests are routed. If the tags in your interface differ from those shown here, use the values in the generated configuration’s outbounds[].tag. Don’t reference a tag that doesn’t exist.

3. Combine the rules in this six-rule order

Xray evaluates routing rules from top to bottom, and the first match wins. When a rule includes both a domain and a port, both conditions must match. Multiple entries in the same domain list are alternatives: matching any one is enough. Don’t put every domain, IP, and port into a single rule, or you may accidentally turn an intended OR into an AND.

OrderMatch conditionOutboundPurpose
1geosite:category-ads-allblockBlock ad-category domains first
2geoip:privatedirectRoute private addresses, including LAN and loopback, directly
3geosite:cndirectRoute the mainland China domain category directly
4geoip:cndirectRoute directly when the known destination IP is in mainland China
5full:example.comproxyExample rule to proxy an exact domain
6network: tcp,udpproxyProxy all remaining requests

Rule 5 uses a documentation example domain to make exact matching easy to verify; you can remove it for everyday use. To force a site already covered by an earlier category to use the proxy, move its dedicated rule above that category. Rules don’t get higher priority just because they’re more specific—their position determines which one is checked first.

Here’s the corresponding Xray routing configuration snippet. It illustrates what the fields mean; it is not a complete configuration that you can run as-is, nor is it an import format for v2rayN’s graphical interface. Before using the interface’s import feature, check the rule structure exported by your version. Don’t import this snippet as a complete rule file.

{
  "routing": {
    "domainStrategy": "AsIs",
    "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",
        "domain": ["full:example.com"],
        "outboundTag": "proxy"
      },
      {
        "type": "field",
        "network": "tcp,udp",
        "outboundTag": "proxy"
      }
    ]
  }
}

geosite:cn is a domain category, not a live check of where a website’s server is located. geoip:cn is a set of IP addresses and does not indicate where a website operator is based. Cross-border CDNs and mainland China sites hosted abroad may behave differently than expected. If an individual site takes the wrong route, adding a domain exception is easier to control than repeatedly changing the entire category.

4. Choose AsIs to keep the fallback from hiding resolution behavior

This example explicitly uses AsIs: it does not resolve domain names just for routing. Requests that include a domain are primarily matched against domain rules; requests that already include an IP can match IP rules directly. So rule 4 does not mean every uncategorized domain is resolved first and then routed directly based on a mainland China IP.

Bottom line: Start with AsIs when using a catch-all fallback

The final tcp,udp rule can also match at the domain stage, so IPIfNonMatch may never get a chance to resolve a domain after a miss. If your routing depends on IP-based fallback matches, redesign the fallback or evaluate IPOnDemand. Simply changing the strategy name does not guarantee that the behavior you want will take effect.

A routing domain strategy and the outbound used for DNS queries are separate things. Choosing AsIs does not mean the system stops making DNS queries or that every lookup goes through the proxy. An app may resolve a domain to an IP before sending the request, a proxy protocol may pass the domain to the remote server, or the core may resolve a direct destination—each creates a different resolution path. First check whether the request reaches the core with a domain or an IP, then investigate why a domain rule didn’t match.

5. Test each route, not just the exit IP

Save and enable the rule set, then check that the core starts normally. If you see errors about a missing domain category or geo data, use the client’s data update feature to update the files for your core version, then restart the core. If it hasn’t started successfully, browser cache or leftover system proxy settings can make the setup appear to work partially.

  1. Test the proxy: Run the command below with the example domain, then check the access log for the proxy outbound tag. If your port isn’t 10808, replace it with the actual HTTP or mixed port shown in the interface.
  2. Test direct routing: Choose a domain you’ve confirmed is included in the current geosite:cn data. Record the domain, time, and outbound tag. A site loading successfully only confirms that the request worked; it doesn’t prove that it went direct.
  3. Test blocking: Choose a known entry in the current ad category and check whether the log shows the block outbound. To test the blocking mechanism, temporarily move a separate full:example.com rule to the top and set it to block. Restore the rule afterward.
  4. Test the fallback: Use a destination not covered by the earlier rules and confirm it goes through the proxy. If UDP traffic fails, also check that the server and transport support UDP forwarding.
curl --proxy http://127.0.0.1:10808 --connect-timeout 10 --max-time 20 -I https://example.com/

The 10-second value in the command is the connection timeout; 20 seconds is the total request limit. Neither is a measured latency. An HTTP status means the request received a response. A closed connection does not necessarily mean a block rule matched, so check the logs. Some sites don’t support HEAD requests; if that’s the case, try a regular GET and compare the routing results.

6. Common split-tunneling issues and fixes

Why is a mainland China site still going through the proxy?

First check that the rule set you just edited is the one currently enabled. Then make sure the proxy fallback isn’t above the mainland China rules. If the order is correct, check whether the core received a domain or an IP, and whether the current geosite data includes that domain. If you need a direct route, add a domain: exception above the fallback rather than routing every unknown request directly.

Why does a login page break after enabling ad blocking?

Temporarily disable the ad-category rule and retry to see whether the problem goes away. If a domain was blocked by mistake, use the logs to identify the login, CAPTCHA, or static asset domain. Add a direct or proxy exception for it and move that rule above the ad block. Don’t allow an entire domain suffix just because the page appears blank.

Why does split tunneling work in the browser but not in another app?

Check whether the app follows the system proxy settings. If it supports manual proxy settings, enter 127.0.0.1 and the actual listening port, then select the appropriate HTTP or SOCKS type. Use Tun only if you need to capture traffic from apps that ignore proxy settings. Before enabling it, check the system permissions and LAN access requirements.

Will a subscription update overwrite my custom routing rules?

Server subscriptions and local routing rule sets are separate configuration objects, so a routine server update usually won’t change a separately saved routing rule set. Importing a complete client configuration or updating a remote routing rule set may change its contents. Keep your exceptions in a maintainable local rule set, and after updates check the active rule set, rule order, and outbound tags.

A maintainable split-tunneling setup should make the purpose of every rule clear: block unwanted traffic first, route LAN and mainland China categories directly when their conditions match, add exceptions for specific domains, and send everything else through the proxy. Verify this baseline before adding dedicated rules for games, downloads, or work services. That makes it easier to pinpoint the cause when something breaks.

Client downloads