Xray routing is an ordered rule system: the first matching rule selects an outbound. The routing.domainStrategy setting controls when Xray resolves a domain so that IP-based rules can participate; it does not replace DNS configuration or guarantee that every application uses the same resolver. This guide explains the three strategies, shows a DNS-aware routing example, and gives a practical procedure for checking which rule actually selected an outbound.
How Xray routing matches traffic
Routing begins after a connection reaches an inbound. Xray evaluates the connection’s available information against the rules in routing.rules. Depending on the inbound and request, that information can include the destination domain or IP address, destination port, network type, source address, inbound tag, and detected protocol. When a rule matches, its outboundTag or balancerTag determines where the connection goes. In the usual configuration, Xray stops at the first matching rule, so rule order is part of the configuration’s behavior—not merely its presentation.
A rule can match a domain, an IP range, or both. Domain entries such as domain:example.com, full:example.com, keyword:example, and regexp:.*\.example\.com$ have different matching scopes. For example, domain:example.com matches the domain and its subdomains, while full:example.com is an exact domain match. An IP entry such as 192.0.2.0/24 matches an address range. Domain and IP rules are not interchangeable: an IP rule cannot match a hostname unless Xray has an IP address available to evaluate.
Use explicit, narrow rules near the top of the list when they must take priority. For instance, a rule that sends a private address range to a direct outbound should precede a broad rule that sends all IP traffic through a proxy. If the broad rule appears first, the private-range exception may never be reached. A final rule with only an outboundTag can serve as a fallback, but it also means that earlier rules should be checked carefully before diagnosing unexpected routing.
| Rule field | What it matches or selects | Practical check |
|---|---|---|
domain | Domain names supplied to routing, using entries such as domain: or full: | Check whether the request arrived with a domain, and whether the entry is exact, suffix-based, or a keyword. |
ip | Destination IP addresses or CIDR ranges | Check whether the destination was resolved and which address was selected. |
port / network | Destination port or connection network, such as TCP or UDP | Confirm the actual connection uses the port and network named in the rule. |
inboundTag / protocol | The inbound that received a connection or a protocol recognized by the core | Check the inbound tag and whether protocol sniffing is enabled and applicable. |
outboundTag / balancerTag | The outbound or balancer selected by a matching rule | Confirm the referenced tag exists in outbounds or routing.balancers. |
domainStrategy and DNS are related but separate
routing.domainStrategy determines how routing handles domain destinations when it needs to evaluate IP rules. It does not tell every application which DNS server to use, nor does it configure a system-wide DNS resolver. Xray’s dns configuration, the operating system’s resolver, an application’s own DNS behavior, and the routing strategy are related parts of a connection path, but they answer different questions. A DNS server entry supplies a name-resolution source; domainStrategy controls whether and when a domain is resolved for routing decisions.
| Value | Routing behavior | When to consider it | Important limitation |
|---|---|---|---|
AsIs | Uses the destination information already available; it does not resolve a domain just to make an IP rule match. | When domain rules are sufficient, or when IP-based routing should use an IP already supplied to the core. | An IP rule may not match a request represented only by a domain name. |
IPIfNonMatch | First tries routing with the available information. If no rule matches, it resolves the domain and tries matching again with the resulting IP information. | When domain-specific rules should get the first opportunity, with IP rules as a fallback. | Resolution can add work after an initial rule pass and depends on available DNS behavior. |
IPOnDemand | Resolves a domain when the routing evaluation needs an IP match, rather than waiting for all rules to fail first. | When IP-based rules should be considered as the rules are evaluated. | Resolution timing can affect which information is available; rule order still matters. |
These strategies are not a ranking from weak to strong. Choose according to the rules you actually use. If all relevant destinations are selected by domain rules, AsIs may avoid unnecessary resolution for routing. If the configuration relies on IP rules for destinations that arrive as hostnames, an IP-resolving strategy may be necessary. If both domain and IP rules are involved, consider which rule should get priority and when a DNS lookup is appropriate.
DNS can also produce more than one address for a hostname. An IPv4-only rule, an IPv6 result, a changed DNS answer, or different resolver paths can make a test appear inconsistent. A DNS-aware routing rule is therefore not a promise that a hostname always maps to one fixed outbound. It is a decision based on the request metadata, the result available at the time, the configured rules, and their order.
Build and test a domain and IP split
The following fragments illustrate the routing logic, not a complete drop-in configuration. They use documentation-only addresses in the reserved 203.0.113.0/24 range and placeholder domain names. Replace the sample entries with domains and IP ranges you are authorized to route. The proxy and direct tags must match outbounds that already exist in the configuration. If you edit a generated client configuration, use the client’s supported custom-configuration mechanism and avoid overwriting unrelated inbound, outbound, or DNS settings.
This example puts an explicit domain route first, then a private-address exception, then a DNS-aware IP rule, and finally a fallback. The order makes the intended priority visible. The sample DNS server is an example value; select a resolver appropriate to your network and policy rather than copying it blindly.
{
"dns": {
"servers": [
"1.1.1.1"
]
},
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"type": "field",
"domain": [
"domain:service.example",
"full:login.example.net"
],
"outboundTag": "proxy"
},
{
"type": "field",
"ip": [
"geoip:private"
],
"outboundTag": "direct"
},
{
"type": "field",
"ip": [
"203.0.113.0/24"
],
"outboundTag": "proxy"
},
{
"type": "field",
"outboundTag": "direct"
}
]
}
}
In a real configuration, a domain entry such as geoip:private is not a domain rule; it belongs in the ip list, as shown above. GeoIP and GeoSite entries also depend on the relevant rule data being available to the running core. If the data is missing or the tag is not supported by the installed core build, the intended match may not occur. For a first test, a clearly named domain and an explicit IP range can be easier to inspect than several imported rule sets.
The example’s IPIfNonMatch setting allows the domain rule to be tested first. If no rule matches the available request information, Xray can resolve the hostname and evaluate IP rules. The private range rule illustrates a direct exception; the documentation range illustrates an IP route to the proxy. Because the final rule selects direct, any request not matched earlier will also go direct. Change that fallback only after confirming the desired policy and the existing outbound tags.
Choose the strategy by the kind of rule that must win
Domain-first routing
- Put specific domain rules before broad rules.
- Use
AsIswhen domain matches are sufficient. - Use
IPIfNonMatchwhen IP checks should follow a failed first pass.
IP-dependent routing
- Confirm the destination can be resolved by the core.
- Choose
IPOnDemandwhen an IP match should trigger resolution during evaluation. - Check IPv4 and IPv6 results and the order of overlapping IP rules.
Keep the DNS source, domainStrategy, rule order, and outbound tags aligned with the routing policy you intend to test.
-
Back up the config
Save a copy of the current core configuration before editing. Record the active core, the selected routing mode, and the existing outbound tags so that a failed test can be rolled back without losing unrelated settings.
-
Set the strategy
In the configuration used by the running Xray core, set
routing.domainStrategyto one ofAsIs,IPIfNonMatch, orIPOnDemand. Do not place this field inside a rule object or inside the top-leveldnsobject. -
Order specific rules
Move narrow domain or IP exceptions above broader matches. Confirm every
outboundTagrefers to a defined outbound. Keep a final fallback only if that is the intended route for unmatched traffic. -
Restart and inspect
Save the file, restart the Xray core through the client, and check the startup log for JSON or rule-loading errors. A client UI may generate or merge configuration, so verify that the running core is using the file you edited.
-
Test one destination
Make a new connection to a known test domain, note its resolved address where available, and inspect the connection log. Repeat with a second destination that should match a different rule. Use fresh connections so that an existing session or connection reuse does not obscure the result.
Conclusion: test the rule path, not just the final webpage
If a page loads, that alone does not prove which rule matched. Compare the destination metadata, the first eligible rule, the selected outbound tag, and the DNS result in the core log. This separates a routing match from a coincidentally successful direct or proxied connection.
Verify rule hits and investigate unexpected routes
Start troubleshooting with the running configuration, not the file you believe the client should be using. Desktop clients can assemble configuration from node settings, global options, custom fragments, and generated defaults. A manually edited file may be valid JSON yet not be the file passed to the current core process. Check which core is running, when it started, and whether the log corresponds to a fresh test connection.
- Confirm the request entered Xray: Check that the application uses the client’s local proxy or another inbound handled by the running core. A request that bypasses the inbound cannot be routed by that core’s rules.
- Check destination metadata: Determine whether the log shows a hostname or an IP address. If it shows only an IP, do not expect a domain rule to match unless the configuration and connection path provide the domain through applicable sniffing behavior.
- Read rules from top to bottom: Identify the first rule whose complete set of conditions matches. A matching domain does not help if an earlier rule already selected an outbound; similarly, an IP rule does not match just because a DNS answer exists somewhere on the device.
- Verify the outbound tag: Check that the selected tag exists and that the corresponding outbound can establish a connection. Routing can select a valid outbound while that outbound later fails to reach the destination.
- Compare DNS paths: Check whether Xray, the operating system, or the application performed the lookup. Different resolvers, cached answers, and address-family preferences can produce different destination IPs.
- Test a new connection: Close or refresh the relevant application session, then create a new request. Existing connections may continue using the route chosen when they were first established.
Why does my domain rule appear to be ignored?
Check the connection log for the destination Xray actually received. If it is an IP, confirm whether sniffing is enabled and applicable to that inbound, and make sure an earlier rule did not already match.
Why does an IP rule work only with IPIfNonMatch?
With AsIs, Xray does not resolve a domain just to satisfy an IP rule. Test the same request with the intended strategy and verify that the core can resolve the hostname using its configured DNS behavior.
Can changing DNS fix every wrong outbound?
No. DNS can change the IP available to an IP rule, but it cannot correct a rule placed too late, a missing outbound tag, or traffic that never entered Xray. Check those conditions separately.
Should I use IPOnDemand for every configuration?
Not automatically. Use it when the rule set needs IP resolution during evaluation, then test domain and IP matches against the expected order. If domain rules alone express the policy, an IP-resolving strategy may add unnecessary lookups.
Change one variable at a time. First verify the active configuration and the request’s destination metadata; next adjust rule order or strategy; then test DNS only if the result depends on a resolved address. If several settings change together, a successful test will not reveal which change mattered, and a failed test will be harder to diagnose.
Finally, treat routing logs and DNS results as time-specific evidence. A hostname can resolve differently later, and a connection can be affected by cache state, network changes, or the application’s own resolver. Record the test domain, time, observed destination, strategy, matching rule, and outbound tag. That short record is usually enough to distinguish a rule-order problem from a DNS-resolution problem or a failure after outbound selection.