Xray routing is an ordered, first-match decision: the core evaluates a connection’s available attributes against rules and sends it to the outbound named by the first matching rule. The routing field domainStrategy controls when Xray resolves a domain to an IP address for IP-based routing; it does not replace DNS configuration, sniffing, or a rule’s position. This guide explains those boundaries and provides JSON examples for domain rules, DNS-assisted resolution, IP ranges, and a repeatable way to validate a change before relying on it.
How Xray evaluates routing rules
Think of routing as a sequence of checks performed after a connection reaches the core. Xray gathers the destination information and other available attributes, tests routing rules in their configured order, and uses the outbound tag selected by the first rule that matches. If no rule matches, the connection uses the default outbound, commonly the first outbound in the configuration. A rule does not create an outbound: its outboundTag must refer to an outbound that actually exists.
Rule fields are conditions, not independent routes. For example, if one rule contains both domain and port, a connection must satisfy both conditions for that rule to match. Multiple values within a field can provide alternatives: a destination matching either listed domain may satisfy the domain condition. When a connection could match more than one rule, order determines which matching rule wins. A broad rule near the top can therefore shadow a narrower rule below it.
| Rule field | What it tests | Common diagnostic question |
|---|---|---|
domain |
A domain name available to the core, such as a domain supplied by the request or identified by sniffing | Does the connection still contain a domain, or does it only contain an IP address? |
ip |
A destination IP address or address range, including CIDR notation | Has Xray resolved the destination to an address before this rule is evaluated? |
port and network |
The destination port or transport network, such as TCP or UDP | Does the rule describe the actual connection rather than the URL alone? |
inboundTag and protocol |
The inbound that accepted the connection and, when identified, the application protocol | Is the request arriving through the inbound tag named by the rule? |
outboundTag |
The outbound selected after the conditions match | Does the tag exactly match an outbound tag in the same configuration? |
In the example below, requests for internal.example use the direct outbound, while other traffic uses the proxy outbound. The two rules are deliberately ordered: a broad catch-all proxy rule placed first would make the direct rule unreachable. The example assumes the configuration also defines outbounds with the tags direct and proxy.
Rule order
- First match
- Stops the search through the rule list
- Specific rule
- Place the intended exception before a broad rule
- No match
- Uses the configured default outbound
- Rule target
outboundTagmust name an existing outbound
If the result seems unexpected, inspect the earlier rules before editing the rule that appears closest to the destination.
Domain matching
domain:example.com- Matches the domain and its subdomains
full:example.com- Matches the exact domain name
keyword:example- Matches a domain containing the keyword
regexp:…- Matches a domain using a regular expression
A domain rule can only match a domain value available to Xray; it cannot infer a name from every encrypted or IP-only connection.
Choose a domainStrategy for IP rules
routing.domainStrategy determines how Xray obtains destination IP information when routing rules need it. It is not a general switch for sending DNS requests through a particular outbound, and it does not mean that every connection will be matched by a domain rule. The appropriate value depends on whether the rules need IP-based classification and when resolution should happen.
AsIs: Xray does not resolve a domain just to make an IP routing rule match. This is a suitable starting point when routing is based on domain names and IP rules do not need to classify domain destinations.IPIfNonMatch: Xray first checks rules using the information already available. If no rule matches, it can resolve the domain and check again so an IP rule may match. This is often a practical choice when domain rules handle the usual cases and IP ranges are a fallback.IPOnDemand: Xray resolves a domain when an IP-based rule needs the address. This can be useful when IP rules are part of the intended routing decision, but it may trigger lookups earlier than a configuration usingIPIfNonMatch. Check the behavior against the rules and core version in use.
These values concern routing decisions, not whether a client application uses DNS successfully. Xray’s dns section configures resolver behavior; routing.domainStrategy controls resolution for routing. A DNS server entry alone does not make a domain rule match traffic that arrived without a domain, and setting IPIfNonMatch does not by itself guarantee that all DNS requests use the proxy outbound.
{
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"type": "field",
"domain": [
"domain:internal.example"
],
"outboundTag": "direct"
},
{
"type": "field",
"ip": [
"geoip:private",
"192.0.2.0/24"
],
"outboundTag": "direct"
}
]
}
}
The address block 192.0.2.0/24 is reserved for documentation and is included only to demonstrate CIDR syntax; replace it with an address range you actually intend to route. The geoip:private rule depends on the GeoIP data available to the core. If you use a GeoIP or GeoSite rule, confirm that the corresponding data files are present and compatible with the Xray version being run. If you do not need those data sets, use explicit IPs or CIDR ranges instead.
Decision: start with the least resolution your rules require
Use AsIs when domain rules are sufficient. Add IPIfNonMatch when unresolved traffic must fall through to IP classification. Choose IPOnDemand only when the rule design benefits from resolving as soon as an IP rule is reached, then verify the result using core logs and a controlled test.
Combine DNS, domain rules, and IP matching
DNS and routing solve related but distinct problems. DNS maps a name to one or more addresses; routing chooses an outbound for a connection. A domain-based rule can match a name already known to the core without requiring an IP lookup. An IP-based rule needs an address to compare against, which may be available because the application connected directly to an IP, because the core performed a lookup, or because the connection was otherwise associated with an address.
Sniffing can help identify a domain from supported application traffic, such as a hostname in an HTTP request or a TLS server name, but it is not a universal recovery mechanism. The application, transport, encryption, inbound, and sniffing settings all affect what the core can identify. In particular, do not assume that a connection to a literal IP address will become a domain match merely because a routing rule lists a hostname.
The following configuration fragment illustrates a DNS server entry associated with a domain and a routing rule that sends the named domain through the proxy outbound. DNS schema details and supported options can vary with the core version, so validate the complete configuration against the Xray binary you actually use. This fragment also assumes that the configuration defines an outbound tagged proxy.
{
"dns": {
"servers": [
{
"address": "1.1.1.1",
"port": 53,
"domains": [
"domain:example.net"
]
},
"localhost"
]
},
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"type": "field",
"domain": [
"domain:example.net"
],
"outboundTag": "proxy"
},
{
"type": "field",
"ip": [
"geoip:private"
],
"outboundTag": "direct"
}
]
}
}
Here, the DNS server’s domains field influences resolver selection for matching queries; it does not itself select a routing outbound. The routing rules remain the mechanism that assigns a connection to proxy or direct. For a real deployment, choose a resolver that is reachable in your network and appropriate for your privacy and routing requirements. Do not copy a public resolver address as if it were guaranteed to be reachable or suitable in every environment.
Consider rule order when combining domain and IP classification. If the domain should always use the proxy, place its domain rule before a broader IP rule that might also match its resolved address. If a private address should always stay direct, place the private-IP exception before a broad rule that sends all domains or all connections through the proxy. Write down the intended precedence first; otherwise, a syntactically valid configuration can still implement the wrong policy.
Edit and test routing safely
Change one routing decision at a time. Client interfaces may generate a configuration dynamically, so first identify which configuration file and core process are actually active. Editing a sample file that the client does not load will not change live routing. In v2rayN, check the active core and its startup log; on other setups, inspect the service command or launcher arguments to find the file passed to Xray.
-
Find the active file
Record the running Xray version and the configuration path from the launch command or startup log. Do not assume that a file named
config.jsonis the one currently in use, especially when a client generates temporary configuration files. -
Back up the file
Copy the active JSON file to a separate backup before editing. Keep a note of the original
domainStrategy, rule order, and outbound tags so you can restore the previous behavior without guessing. -
Make one change
Add or reorder one rule, or change
domainStrategy, but do not change the DNS server, inbound, and outbound at the same time. Confirm that every rule’soutboundTagexists and that the JSON uses commas and quotation marks correctly. -
Validate the JSON
Run the Xray binary with
run -test -config path/to/config.json, replacing the path with the active file. Use the equivalent executable name on your system. A successful test checks that the core can parse and validate the configuration; it does not prove that a particular request will match the rule you intended. -
Test one destination
Restart or reload the core using your normal client or service workflow. Test one known domain and, separately, one known IP destination. Check the core log and confirm the observed outbound before changing another rule.
For a useful test, keep the inbound, node, and client application constant. Test both a hostname and an IP where possible, because the two requests may supply different matching information. If switching domainStrategy changes the result, record the before-and-after behavior and the resolver used. A repeated test against the same destination helps separate a routing change from DNS rotation, a different server address, or a changed node.
Diagnose rules that miss or select the wrong outbound
Start with the evidence that identifies the actual request path: the active core configuration, the inbound tag, the destination as seen by the core, the order of matching rules, and the outbound selected in the log. A browser’s displayed hostname alone is not sufficient evidence that Xray received that hostname. Likewise, a successful DNS lookup does not prove that the resulting connection matched the intended IP rule.
Why does my domain rule never match?
Check whether the active inbound enables suitable sniffing and whether the connection exposes a supported hostname. Then test the exact domain pattern, including whether you need a subdomain match or an exact match. If the connection reaches Xray only as an IP address, an IP rule or a configuration that can identify the domain may be needed instead.
Why does the IP rule work for one domain but not another?
Compare the addresses returned for both names and verify that the core can resolve them under the active DNS configuration. A domain may return several addresses, change between lookups, or be answered by a different resolver. Check the CIDR range and use IPIfNonMatch only when resolution after an initial rule miss fits the intended rule order.
Why does traffic still use the default outbound?
Confirm that the request reaches the core, that the rule’s conditions match the request, and that no earlier rule sends it elsewhere. Check the exact spelling of outboundTag against the outbound list. If no rule matches, Xray falls back to the default outbound rather than treating a missing tag as an instruction to use the desired route.
Does changing domainStrategy change all DNS traffic?
No. It affects domain resolution for routing decisions that need IP information. Inspect the separate dns configuration and the application’s DNS behavior when troubleshooting resolver selection. Then test the chosen outbound independently from the question of which resolver answered the name.
If a rule appears to match but traffic takes an unexpected path, temporarily simplify the relevant rules while preserving a backup. Remove unrelated conditions, leave one clearly identifiable test rule, and verify the result. Reintroduce conditions in small steps. This method is more reliable than adding a second broad rule, because extra rules can hide the original ordering or resolution issue.
Finally, check that the configuration being tested is the configuration being run. A client may merge subscription-generated settings, maintain separate core profiles, or regenerate JSON when a setting changes. Validate the active file after the client has produced it, not only an edited source fragment. Once the desired behavior is confirmed, retain the tested rule order and record the core version alongside the configuration change.