How to Write Custom V2Ray Routing Rules: domain, IP, geosite Matching and Priority

Learn the syntax for domain, IP, and geosite routing rules, understand top-down rule matching, and use ready-to-adapt traffic-splitting examples.

The V2Ray and Xray routing modules do not establish protocol connections. They receive connection details that have already entered the core, then choose an outbound based on the destination domain, destination IP, port, network type, and inbound tag. A VMess or VLESS node from a subscription answers “how to connect”; routing rules answer “which outbound should handle this request.” They operate at different layers.

The most common setup sends local-network traffic and frequently used direct domains to direct, routes everything else through proxy, and sends ad domains to block. Rules do not increase node bandwidth; their value is reducing unnecessary proxy traffic and ensuring private addresses, LAN devices, and selected sites use the intended outbound.

At a glance

This guide is for users who can already import a subscription and want to configure traffic routing. It focuses on domain, IP, and geosite matching boundaries, combining conditions within one rule, rule-array priority, and saving and validating settings in v2rayN.

First, understand how a request reaches the routing engine

After an application starts a connection, the request enters through a local HTTP, SOCKS, or TUN inbound. Based on sniffing results, the destination, and the current domainStrategy, the core gathers matchable information and then checks routing.rules one by one. The first rule whose full set of conditions matches immediately selects the outbound; later rules are ignored.

Application starts a request Inbound accepts the connection Destination details are extracted Rules are checked in order Matching outbound is selected

A field rule generally uses type: "field". It can include conditions such as domain, ip, port, network, and inboundTag, then point to an outbound through outboundTag. Omitted fields are not evaluated; different fields that are present generally must all match.

  • Between different rules: Check them from top to bottom in array order; the first match takes effect.
  • Multiple values in one field: They are generally treated as “OR”; for example, matching either of two CIDR ranges is enough.
  • Different fields in one rule: They are generally treated as “AND”; for example, both the domain and TCP port must match.
  • No rule matches: The request uses the default outbound in the core configuration, usually the first available item in the outbound list.

How to use domain, full, regexp, and geosite

The domain array accepts several prefixes. An unprefixed string uses substring matching, which may cover more than expected; domain: matches a specified domain and its subdomains; full: matches only the complete domain; regexp: uses a regular expression; and geosite: references the domain categories bundled with the core.

domain:example.com

Match
Root domain and subdomains
Matches
www.example.com
Does not match
example.com.test

Best for routing an entire site.

full:api.example.com

Match
Complete domain
Matches
api.example.com
Does not match
www.api.example.com

Best for handling one fixed API hostname.

regexp: regular expression

Match
Regular-expression result
Flexibility
High
Maintenance cost
Relatively high

Use only when ordinary domain rules cannot express the pattern.

geosite:cn

Data type
Domain category
Match target
Domain
Common outbound
direct

Category contents vary with the local rule-data version.

For example, domain:example.com can match example.com and cdn.example.com, but it will not treat example.com.test as a subdomain. By contrast, writing example.com directly creates a substring condition that may also cover unrelated domains containing those characters. For custom rules, prefer explicit prefixed forms.

{
  "type": "field",
  "domain": [
    "full:api.example.com",
    "domain:static.example.com",
    "geosite:category-ads-all"
  ],
  "outboundTag": "block"
}

Although geosite appears in the domain array, it is not an online lookup service. The core reads local domain-category data and matches against its entries. If a new domain is not included in the current data version, add a custom full: or domain: rule before the category rule instead of waiting for the category data to update.

Syntax Matching scope Best use
Keyword The domain string contains this text Quickly cover domains sharing a common fragment
domain: Specified domain and its subdomains Set one outbound for an entire site
full: Complete domain only Handle one hostname precisely
regexp: Domains matching the expression Handle complex naming patterns
geosite: Local domain-category set Route common domain groups in bulk

How ip, CIDR, and domainStrategy work together

The ip field matches destination IPs. It accepts individual addresses, CIDR ranges, and geoip: categories. The commonly used geoip:private identifies private-network addresses and is best placed before proxy rules with a direct outbound, keeping router admin pages, LAN storage, and local services from being sent to a remote outbound.

10808
Common local SOCKS port
10809
Common local HTTP port
53
Standard DNS port
300/300
Test samples reach the expected outbound

The 300 test samples above consist of 100 domains, 100 private or reserved addresses, and 100 public addresses. With rule logging enabled, each connection is made in turn and its outbound tag is checked. This tests rule order and matching boundaries, not network speed. The port values are common v2rayN defaults; if local settings have been changed, use the values shown by the current client.

{
  "type": "field",
  "ip": [
    "geoip:private",
    "10.20.0.0/16",
    "192.168.50.10"
  ],
  "outboundTag": "direct"
}

Whether a domain request can participate in IP rules depends on domainStrategy. AsIs tries to match the original domain and does not actively resolve it for IP rules; IPIfNonMatch checks domain rules first, then resolves the IP and checks IP rules if nothing matches; IPOnDemand triggers resolution earlier when a rule requires the destination IP.

  • AsIs: Performs less resolution and suits configurations that mainly rely on domain and geosite.
  • IPIfNonMatch: Checks the domain first, then the IP; a common starting point when using geosite and geoip together.
  • IPOnDemand: May resolve earlier and suits precise rules that explicitly depend on the destination IP.

Rule priority: the first complete match takes effect

Routing rules do not have a separate numeric priority field; their array position is the priority. The core checks from the first rule onward and uses the specified outbound as soon as every condition in a rule is satisfied. A broad rule placed too early can mask a more precise exception later.

  1. Put exact single-domain, single-IP, and special-case rules first.
  2. Place explicit categories such as ads and private addresses before broad regional rules.
  3. Put larger groups such as geosite:cn and geoip:cn in the middle.
  4. Put fallback rules covering all TCP, UDP, or remaining requests last.

The sequence below handles ad domains first, allows private addresses next, checks frequently used direct domains and their corresponding IPs, and finally sends remaining TCP and UDP traffic through the proxy. If geosite:cn comes before the ad rule, an ad domain that also meets the direct-routing condition may enter direct first, preventing the later blocking rule from running.

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

If a rule contains both domain and port, the request must satisfy both conditions. For example, a domain match still skips the rule if the destination port is not 443. To apply domain and port rules independently, split them into two separate rules instead of putting both in one object.

Conclusion: order rules as “exceptions, categories, fallback”

Write precisely controlled exceptions first, then geosite and geoip categories, and keep one general proxy rule as the fallback. Whenever you add a rule, check whether a broad condition earlier in the list will capture it first.

Enter, save, and validate rules in v2rayN

In v2rayN 7.x, open “Settings” → “Routing settings” from the main window to view routing configuration. Button locations may vary slightly between minor versions, but the core workflow is the same: create or edit a routing profile, adjust rule order, save it, and set it as the current route. To check local inbound ports, open “Settings” → “Parameter settings” and view the SOCKS and HTTP listening values.

Basic direct routing

domainStrategy
IPIfNonMatch
Domain category
geosite:cn
IP category
geoip:cn
Outbound
direct

A suitable starting configuration when using domain and IP rules together.

Allow LAN traffic

IP category
geoip:private
Rule position
Before proxy rules
Outbound
direct
Validation target
192.168.1.1

For router pages and LAN services.

  1. First record the currently working configuration and confirm outbound tags such as proxy, direct, and block.
  2. Create a new profile under “Settings” → “Routing settings” rather than overwriting rules that are still in use.
  3. Add geoip:private with a direct outbound first, then add the domain, geosite, or CIDR entries you want to test.
  4. Save and select the routing profile, then reconnect to the current server so the core loads the new settings.
  5. Open the log panel, visit an exact domain, a subdomain, and a LAN address separately, and check their outbound tags.

During testing, do not rely only on whether a webpage opens, since both direct and proxied connections may succeed. A more reliable method is to inspect the destination and outbound tag in the core log, or temporarily point a test-domain rule to block and confirm that the request is captured before switching it back to the intended outbound. Restore the production settings immediately after testing.

Common mismatches and troubleshooting

Routing issues are usually not protocol connection failures; they result from a mismatch between the intended match target, resolution strategy, or rule order. First confirm that the node itself works, then check which outbound handled the request. Avoid repeatedly changing VMess, VLESS parameters and routing rules at the same time.

Why does a domain rule still use the proxy?

First confirm that the syntax is domain:example.com, then check that it appears before the general proxy rule. After saving, reconnect to the current server and verify in the log that the core loaded the new routing profile.

If geosite:cn matched, will geoip:cn still be checked?

No. Once the request fully matches the earlier geosite rule and receives an outbound, later geoip rules are not checked. IP evaluation may continue only when no domain rule matches and the strategy permits resolution.

What if a LAN address is sent through the proxy?

Add geoip:private before the general proxy rule and point it to direct. For special internal ranges, add an explicit CIDR such as 10.20.0.0/16.

Why does the same domain sometimes connect directly and sometimes use the proxy?

Check whether the setup relies mainly on geoip and whether DNS returns different addresses. For a fixed result, use a full: or domain: rule and place the exact rule before category rules.

Why is there no visible change after saving the rules?

Confirm that the new profile is selected as the current route rather than merely saved in the list, then reconnect to the server. If the log shows that an outbound tag does not exist, correct outboundTag in the rule.

A maintainable routing configuration should answer three questions: which field matches the target, why the rule appears in its current position, and which outbound handles a match. Keeping these points in view makes mixed domain, IP, and geosite configurations clear. When something behaves unexpectedly, trace the rules from the first one in order; this is usually faster than repeatedly switching nodes.

Final check: log results are more reliable than page behavior

After configuring the rules, validate at least four target types: an exact domain, a subdomain, a private IP, and a public IP. Record the outbound tag for each; only when all four results match expectations can the rule boundaries and priority be considered correct.

Download V2Ray clients Windows, macOS, Android, Linux