This guide is for users who already have v2rayN, v2rayNG, or v2flyNG working and want more control over which requests go direct, through a proxy, or to a block rule. It explains the matching boundaries of domain, IP, and geosite rules, top-down priority, and multi-condition combinations, with Xray routing examples you can verify directly.
Understand what routing rules handle
The V2Ray and Xray routing modules do not establish node connections. They decide which outbound handles a connection after it enters the core. Common outbound tags are proxy, direct, and block, representing proxying, direct access, and blocking. These names are not protocol keywords; they are outboundTag values defined in the configuration. If the client generates different tags, use the names it actually generates.
A request may contain a domain, destination port, inbound source, and resolved IP at the same time. Rules are checked in order, and the first complete match usually determines the outbound. The key ordering principle is simple: put specific rules first and broad rules later. Placing broad matches such as geosite:cn or geoip:cn first may prevent a later proxy rule for a specific domain from ever taking effect.
Multiple values in the same field mean “match any,” while different fields must all match. For example, a rule containing both domain and port requires both conditions to be true; three domains in a domain array match if any one of them matches. This distinction often makes a rule look correct while leaving the intended requests uncovered.
| Match target | Typical syntax | Best suited for | Key limitation |
|---|---|---|---|
| Domain | domain:example.com |
Routing websites, APIs, and download domains | The application must pass the domain to the core, or allow the core to resolve it |
| IP | 192.0.2.0/24 |
Routing fixed networks, LAN traffic, and resolved addresses | Whether domain requests are converted into IP matches depends on domainStrategy |
| geosite | geosite:category-ads-all |
Batch matching maintained domain categories | Depends on the geographic data file and category labels currently used by the client |
| geoip | geoip:private |
Private addresses or country and regional IP ranges | Matches destination IPs only; it is not equivalent to geosite domain classification |
Five common domain patterns
domain: is the most practical format for routine domain rules. domain:example.com matches example.com and its subdomains, such as api.example.com, but does not treat notexample.com as the same suffix. Use this form when you want to cover a site and all of its service subdomains.
full: performs an exact hostname match. full:api.example.com matches that host, but not www.example.com or v2.api.example.com. It is useful for sending one API through a proxy while letting other services under the same parent domain follow general rules.
A plain string without a prefix performs substring matching. For example, example may match any part of a domain containing that text, often covering more than intended. regexp: supports regular expressions and offers the most flexibility, but becomes harder to troubleshoot as rules grow and is more prone to unintended matches when boundaries are too loose. If domain: or full: expresses the requirement, there is no need to start with a regular expression.
domain suffix matching
RecommendedCovers the parent domain and all subdomains with clear semantics, making it suitable for most website rules.
Best for: routing an entire site through a proxy or direct connection
full exact matching
Handles one specific hostname without extending to other services under the same parent domain.
Best for: a single API or download domain
regexp regular-expression matching
Can describe complex naming patterns, but you must handle escaped dots and start and end boundaries yourself.
Best for: large sets of patterned subdomains
{
"type": "field",
"domain": [
"full:api.example.com",
"domain:static.example.net",
"regexp:^img-[0-9]+\\.example\\.org$"
],
"outboundTag": "proxy"
}
The three domain entries above are an “or” condition. A request only needs to match one of them before the rule’s other fields are checked. Because the example has no additional fields, it can go straight to the proxy outbound. The dots in a regular expression must be escaped, and the backslash must also be preserved in the JSON string, so the configuration contains \\..
How IP, CIDR, and domainStrategy work together
IP rules can contain a single address or a CIDR range. An IPv4 address can be written as 192.0.2.10, while a range can be written as 192.0.2.0/24; IPv6 supports forms such as 2001:db8::/32. The number after the CIDR slash is the network prefix length. /24 covers 256 IPv4 addresses; it is not a port number or an address count.
geoip:private is commonly used to send private addresses directly, covering typical LAN ranges. Your configuration should also handle loopback addresses and local services so router admin pages, NAS devices, or programs running on 127.0.0.1 are not sent through a remote proxy. v2rayN commonly listens for SOCKS on 10808; its HTTP port may use the same mixed entry or an adjacent port. Check the actual value under Settings → Parameter Settings → local listener settings.
- AsIs: Match the domain carried by the request first; do not resolve it just to try IP rules.
- IPIfNonMatch: Check domain rules first. If none match, resolve the destination domain and then try IP rules.
- IPOnDemand: Trigger resolution as soon as a rule may require the destination IP. This suits configurations that explicitly depend on IP routing, but introduces DNS results earlier.
- Direct IP requests: When the application connects to an IP address directly, there is no domain to resolve. IP and geoip rules can participate in matching immediately.
{
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"type": "field",
"ip": [
"geoip:private",
"127.0.0.0/8",
"192.0.2.0/24"
],
"outboundTag": "direct"
}
]
}
Conclusion: domain exceptions come before broad IP rules
If a domain must use a proxy but may resolve to an address range covered by a direct rule, place its proxy rule before that IP direct rule. Use the logs to confirm whether the request initially carried a domain or only an IP.
How to use geosite categories
geosite is a data classification organized into domain sets, not a real-time lookup service. geosite:cn represents domains assigned to that category in the data file, while geosite:category-ads-all is typically used for an advertising-domain set. Category contents vary with the data version bundled with the client, so geosite works best for broad baseline routing; important custom domain exceptions should still be listed separately above it.
geosite and geoip are not interchangeable. A domain’s membership in a geosite category does not mean its current IP belongs to the corresponding geoip category. With a content delivery network, the same domain may also resolve to different addresses in different network environments. Use geosite for domain semantics first, then geoip as a fallback for unmatched connections; this is usually easier to maintain than looking at IPs alone.
Pay special attention to the order of block categories. Suppose a business API is included in an advertising category even though the page needs it to load normally. A broad block rule will block it as well. The solution is not to remove every advertising category; add a full: or domain: exception before the block rule and send it to direct or proxy.
[
{
"type": "field",
"domain": [
"full:required-api.example.com"
],
"outboundTag": "proxy"
},
{
"type": "field",
"domain": [
"geosite:category-ads-all"
],
"outboundTag": "block"
},
{
"type": "field",
"domain": [
"geosite:cn"
],
"outboundTag": "direct"
}
]
Match priority and rule-editing workflow
Priority is not automatically determined by whether a rule uses domain, IP, or geosite. It is mainly determined by the rule’s position in the array. The core checks from the first rule onward and stops after a match, so later rules cannot override the result. Put single-domain exceptions before category rules, category rules before the final fallback, and never place a block rule above business exceptions without a condition.
The wording in v2rayN 7.x may change between minor releases, but the checking workflow remains the same: identify the core in use, open the routing settings, then verify the active routing profile and rule order. After editing, restart the core or reload the configuration; saving the window alone does not replace the configuration currently running.
Confirm the core
Open Settings → Parameter Settings → Core Type and confirm whether the configuration uses the Xray or v2fly core. The selected core must support the protocols and routing fields in use.
Open routing settings
Go to Settings → Routing Settings and select the active routing configuration. If several profiles are available, first confirm the profile name selected on the main screen.
Add exceptions
Add required proxy or direct
full:anddomain:rules first, then add broader categories such as geosite and geoip.Verify the outbound
Check whether each rule targets the proxy, direct, or block outbound. When editing the raw configuration, also confirm that
outboundTagmatches an existing outbound tag exactly.Reload and verify
Save and restart the core. Test one domain matching an exception, one domain matching a category, and one LAN address, then check the core logs for the actual routing result.
Conclusion: order rules from narrow to broad
Expand the scope from exact hostnames to domain suffixes, geosite categories, geoip ranges, and finally the fallback. This reduces the chance that a broad rule captures a request too early; genuine business exceptions should always come before the broader category they override.
Direct, proxy, and block routing example
The complete routing snippet below demonstrates the structure. It sends a specified API through a proxy, blocks the advertising category, sends the LAN and specified domains directly, and routes anything not handled above through the proxy. Before using it, confirm that the configuration defines three outbounds named proxy, direct, and block.
{
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"type": "field",
"domain": [
"full:api.example.com",
"domain:services.example.net"
],
"outboundTag": "proxy"
},
{
"type": "field",
"domain": [
"geosite:category-ads-all"
],
"outboundTag": "block"
},
{
"type": "field",
"domain": [
"domain:printer.example.lan",
"geosite:cn"
],
"outboundTag": "direct"
},
{
"type": "field",
"ip": [
"geoip:private",
"127.0.0.0/8"
],
"outboundTag": "direct"
},
{
"type": "field",
"network": "tcp,udp",
"outboundTag": "proxy"
}
]
}
}
The final rule only specifies network, covering TCP and UDP, so it acts as the fallback. It must be placed at the end of the array. If placed first, nearly every common connection will immediately use the proxy, and later direct and block rules will never be checked. If you only want to proxy TCP, do not include UDP in the fallback; DNS or real-time communication traffic could otherwise change its outbound.
Port conditions can be combined with domains. For example, with domain:example.com in domain and 443 in port, only access to port 443 on that domain matches. Access to port 80 on the same domain continues to the following rules. Port ranges can use the format supported by the core, but routine configurations should stay limited to clearly defined service ports to avoid broad coverage that is difficult to explain.
- Test the proxy exception: visit the domain explicitly listed in the first rule and confirm that the logs show
proxy. - Test the block rule: choose a domain known to belong to the current geosite category and confirm that the connection is sent to
block. - Test LAN direct access: open a router or LAN service address and confirm that it matches
geoip:privateor the intended CIDR. - Test the final fallback: choose a target that belongs to none of the preceding categories and confirm that the last rule handles its outbound.
Troubleshoot rules that have no effect
Troubleshooting starts with two questions: “What target did the core actually receive?” and “Which rule matched first?” When a browser opens a domain, the core may receive the domain or only the IP resolved by an upstream application. Transparent proxies, system proxies, and in-app proxies do not expose exactly the same information. Do not assume from the browser address bar that the core received a domain.
Next, check whether the client regenerated and loaded the configuration. After changing a routing profile in v2rayN, edits do not affect actual traffic if the main screen is using a different profile. When v2rayNG or v2flyNG uses a subscription configuration, distinguish subscription updates from local routing edits so an update does not overwrite your changes.
Why does a domain-specific rule still go direct?
Move the domain rule above geosite:cn and geoip:cn, and confirm that its outboundTag points to the proxy. Then restart the core and use the logs to check whether an earlier direct rule matched first.
Why does adding a geosite tag prevent startup?
Check the exact tag name in the core error log and confirm that the current data file contains the category. Start with a common category as a minimal test instead of adding several tags from unknown sources. If the tag does not exist, replace it with an explicit domain: rule.
Why do domain rules match while IP rules do not?
Check domainStrategy. When IP matching should be attempted after domain rules fail, use IPIfNonMatch; after changing it, also verify that DNS returns the expected address.
Why is the LAN admin page being sent through the proxy?
Add direct rules for geoip:private and the required LAN CIDR ranges before the final proxy fallback. If the service uses a custom LAN domain, add a matching full: or domain: direct rule as well.
Why did saving the rules change nothing?
Confirm that the main screen is using the routing profile you just edited, then restart the core. Also check Settings → Parameter Settings → Core Type so a configuration intended for another core or data set is not mistaken for the active one.
When maintaining rules, change one target at a time: first route a clearly defined domain, then expand to geosite categories, and finally handle IP and geoip fallbacks. Keep one proxy, one direct, and one block test target for every change. This makes it easier to locate changes after a subscription, core, or geographic data update.