Configuration baseline: Establish a reproducible working state first
Build a minimal working path
Advanced tuning should not start by enabling every option. Start with a minimal path that can be verified repeatedly. Keep one known-working subscription, one server, the default routing, and the client’s default DNS; disable LAN sharing, TUN, FakeDNS, and extra outbounds. On desktop, select a server in v2rayN and enable the system proxy. On Android, select a comparable server in v2rayNG or v2flyNG and connect. Verify only three outcomes: the client core starts, browser requests use the expected egress, and local network resources remain reachable. If any result fails, return to the subscription parameters or server status instead of adding more routing rules.
A baseline should include clear records. Note the current client, core family, subscription group, active server, system proxy mode, and whether remote DNS is enabled. The goal is not to maintain a complicated inventory, but to answer exactly which setting changed after an edit. A subscription update may replace server objects, but it usually will not restore manually edited global routing, so inspect subscription state and global configuration separately.
Separate the four configuration layers
A working V2Ray graphical client configuration usually has four layers. The first is the server object, which stores the address, port, user identifier, transport, and security parameters. The second is subscriptions and groups, which determine how servers are updated, displayed, and filtered. The third is local interception, including the system proxy and TUN. The fourth is the core configuration, including DNS, routing, inbounds, and outbounds. A successful server connection only shows that the first layer is basically correct; it does not prove that DNS or split routing behaves as intended. Conversely, a browser failing to load a page does not necessarily indicate a server problem: the system proxy may not cover that application, DNS may return unsuitable results, or a rule may send traffic to the wrong egress.
| Configuration layer | Primary objects | First verification | Typical scope |
|---|---|---|---|
| Server | Address, port, protocol, transport | Whether the core can establish a connection | Single server |
| Subscription | Updates, groups, filters | Whether servers are categorized correctly | Group of servers |
| Interception | System proxy, TUN | Whether the target app enters the client | Single app or entire system |
| Core | DNS, routing, inbounds, outbounds | Where the request ultimately goes | All matching traffic |
Backups, naming, and rollback
Before editing, use the client’s export or backup function to save the current state. Name the file by purpose, such as “Default routing,” “Before TUN test,” or “Before merging subscriptions.” Do not pack multiple experiment goals into one backup name. If the client supports routing profiles, duplicate the current profile before editing; if it supports only one global configuration, copy the core configuration text first. During rollback, also check the system proxy state, because restoring a configuration file does not always restore the operating system’s proxy switch.
Names should describe purpose rather than emotional judgments. “Work: direct-first,” “Global proxy test,” and “Keep local domains direct” are easier to maintain than “Config one” or “Fastest config.” Server names can retain the provider’s original region, protocol, and multiplier information, while filters should target stable fields. Do not rely on list positions, which may change after a subscription update. Use fixed labels such as direct, proxy, block, and dns-out for routing and outbounds to reduce reference errors.
Use logs to confirm that changes take effect
After each change, reload the core and check the logs for configuration parse errors, port conflicts, insufficient permissions, or failed DNS requests. Start with the information log level; switch briefly to debug only when investigating a specific issue, then switch back so connection details do not bury important events. Read from the first error rather than guessing backward from the last line. If failed to parse config appears, check JSON commas, field nesting, and label references. If the core starts successfully but requests time out, investigate the server, DNS, and routing.
After the baseline passes, make a copy of the configuration before moving to the next section. Apply the same principle throughout: define the goal, change one layer, reload, verify with logs and real access results, then roll back if it fails. For specific error messages, use How to read V2Ray runtime logs to locate the issue step by step instead of repeatedly reinstalling the client.
Subscription Groups and Server Filtering: Manage the list without manually deleting nodes
Separate subscription sources from working views
A subscription source provides server objects; a group organizes those objects into a view suited to selection. They should not be treated as the same layer. Deleting temporarily unused servers seems simple, but they usually return with the next subscription update. A more durable approach is to retain the complete source and control what appears through groups, notes, and filters. v2rayN works well for managing large desktop server lists by subscription group, while v2rayNG and v2flyNG are better suited to a smaller set of mobile candidates, reducing scrolling and accidental selections.
When creating groups, divide them by source first, then build filter views by purpose. For example, “Primary subscription” and “Backup subscription” describe sources, while “Daily use,” “Low multiplier,” and “Preferred protocol” describe purposes. Source groups support updates and fault isolation; purpose filters support actual selection. Do not give different sources identical names, or it will be difficult to identify the affected scope when an update fails. Put manually added servers in a separate group so they are not mistaken for objects synchronized from a source.
Design maintainable filter expressions
Server filters typically use regions, protocols, multipliers, or purpose tags in the name. First observe the stable structure of subscription names, then write inclusion and exclusion rules. If names consistently follow “region | protocol | multiplier,” combine keywords; if separators vary, rely only on stable terms. Regular expressions are useful for combining synonymous names, but keep them short. To filter “Hong Kong or Singapore,” use Hong Kong|HK|Singapore|SG; to exclude test or expired objects, use Test|Expired|Remaining traffic. When inclusion and exclusion rules are both present, confirm the client’s evaluation order first. A common pattern is to retain included items, then remove exclusions from that result.
Include:
Hong Kong|HK|Singapore|SG
Exclude:
Test|Expired|Remaining traffic|Official site
Protocol preference:
VLESS|VMess|Trojan
Multiplier filter:
(^|[^0-9])1(\.0)?x([^0-9]|$)
Multiplier filters are especially prone to false matches. Searching only for the character 1 may match ports, IDs, or “1.5x,” so constrain the boundaries whenever possible. When subscription naming is inconsistent, do not treat a multiplier filter as a billing reference; verify the provider’s information first, then use name filters only to organize the list. A region filter describes a name tag, not the actual network path. Server selection should also consider real connection tests, protocol compatibility, and actual access performance. See How to filter servers by latency, multiplier, and region for a practical method.
Separate sorting, testing, and selection
List sorting narrows the candidates, latency testing removes unreachable objects, and final selection should still be based on the actual workload. Basic latency reflects only the response from a probe target; it does not fully represent page loading, persistent connections, or large-file transfers. Real connection latency is closer to the time required for the core to establish a proxy connection, but it is also affected by the test target and current network conditions. The right workflow is to filter down to a small candidate set, run real connection tests, and validate with the actual application. Do not permanently encode a single test result in a group name.
After automatic sorting, keep one verified, stable server as a fallback. It does not need to stay at the top, but it should have a clear note. Users who update subscriptions frequently can limit sorting to the current group to avoid mixing servers from different sources and purposes. If a group suddenly becomes empty, disable the filter and inspect the raw list first. If the raw list still contains servers, the filter no longer matches; only an empty raw list calls for checking the subscription update.
Handle duplicate names and repeated objects
Multiple subscriptions may provide servers with the same display name. Do not assume they are identical based only on that name. Any difference in address, port, user identifier, transport parameters, or source means they are different objects. A deduplication feature based on the complete configuration is usually safe; one based only on remarks may delete valid candidates. A safer approach is to preserve source information at the group level and distinguish entries with display prefixes instead of changing core parameters inside the subscription.
Filter rules need periodic reverse checks: inspect excluded items for valid servers and review uncategorized items for new naming patterns. After each subscription update, there is no need to redo everything; sample the included, excluded, and unmatched sets. This keeps the list clean without losing usable servers to overly strict expressions.
Multiple Subscriptions: Isolated updates, priorities, and failover
Define the roles of primary and backup subscriptions
Multiple subscriptions are not about piling every server into one list. They assign clear roles to different sources. The primary subscription handles everyday use; the backup is enabled only when the primary source fails to update, a protocol is incompatible, or a particular region is unavailable. A manual group stores long-term fixed entries or temporary test objects. Clear roles prevent update problems from spreading across the entire list. In v2rayN, update subscription groups separately and inspect the results. On mobile, limit the number of enabled groups to avoid rebuilding an oversized server list on every refresh.
Keep a separate note for each subscription and record its filter conditions. Do not mix source-based and purpose-based naming in one group. “Primary subscription” and “Backup subscription” are sources; “Work” and “Streaming test” are purposes. When cross-management is needed, generate candidates with a filter view from the source groups instead of moving the original objects. The view can then be recalculated after updates while the source boundaries remain intact.
Plan update order and failure handling
Update subscriptions one source at a time. Update the primary first, verify that the returned content parses, the server count has not changed unexpectedly, and the known stable entry still exists; then update the backup source. Updating everything at once saves clicks but makes it difficult to identify which address, content format, or network path failed. If the client reports success but the list is empty, check whether the filter excluded every item. If parsing fails, keep the old list and inspect the subscription URL and response format instead of clearing local data first.
When an update fails, distinguish among three cases: the request did not complete, content was returned but could not be parsed, or parsing succeeded but the result was unexpected. For an incomplete request, start with the network, system proxy, or subscription URL. For a parse failure, focus on content format and client compatibility. For an anomalous result, compare names and groups before and after the update. A backup subscription should preserve connectivity, not automatically replace the primary. Once the primary source recovers, switch back in the normal order instead of changing both sources repeatedly.
Set boundaries for automatic updates
Automatic updates suit stable sources, but they should not be bound to automatic server selection as an unobservable black box. When subscription content changes, new objects may move to the top under the sorting rules. If the client also selects the first item automatically, the actual egress can change without an explicit action. A safer setup allows scheduled refreshes while retaining the current active server, switching manually only when that server fails. For highly stable environments, reduce the update frequency and export the configuration before updating.
When using the same subscription across devices, do not insist on identical lists. Keep more regions and protocols on desktop for testing, and retain only common candidates on Android. Synchronization should focus on group logic, routing targets, and DNS policy rather than list order. Clients expose subscription fields, routing interfaces, and core options differently; copying an entire data directory may import platform-specific settings.
Keep subscription content from polluting global configuration
Ideally, a subscription update changes server objects without overwriting global DNS, routing, or local inbounds. If the client offers an option to import additional configuration during updates, understand which layers it changes before enabling it. An unknown routing template may alter the default egress, and a remote DNS setting may replace a verified resolution path. For production-style use, keep global rules in a local configuration profile and use subscriptions only as server sources.
Manual servers need isolation too. Put them in a separate group with clear notes rather than disguising them as subscription objects. Copy a manual object before editing and keep the original as a fallback. If two configurations differ only in transport, state the difference in their names, such as “WS test” and “gRPC test,” rather than “Backup one” and “Backup two.” These details directly affect later log analysis.
| Source type | Recommended update method | List strategy | Action on failure |
|---|---|---|---|
| Primary subscription | Update separately and spot-check | Keep everyday candidates | Pause refreshes and use the old cache |
| Backup subscription | Update infrequently | Keep only key regions | Switch temporarily without replacing the primary source |
| Manual entries | Edit as needed | Separate group | Copy before editing and keep the original |
Perform controlled failover
Before switching, confirm that the problem is actually with the current server rather than DNS or local interception. Select a backup server, reload the core, check the active outbound in the logs, and repeat an access test against the same target. After a successful switch, record the trigger; do not immediately delete the original object, since it remains useful for comparison when the network path recovers. If every server in the primary subscription fails while the backup works, first inspect the protocol or transport conditions shared by the primary source. If both sources fail, return to the system proxy, TUN, DNS, and local network layers.
After organizing multiple subscriptions, you should be able to answer four questions within a minute: which subscription provides the current server, which backup group to use when updates fail, which filters hide servers, and whether global routing is independent of subscriptions. If answering still requires searching through long lists, the group names or responsibilities are not clear enough. Organize them before moving on to complex routing.
Routing Rules in Practice: Determine traffic egress by match order
Understand the decision path from inbound to outbound
Routing rules process connections that have already entered the core. An application first enters through an inbound via the system proxy, TUN, or a local proxy port. The core then reads the domain, destination IP, port, network type, process, or inbound tag and selects an outbound according to rule order. Routing cannot intercept traffic that has not entered the client, nor can it fix incorrect server parameters. Before configuring rules, confirm in the core logs that the application request has arrived, then decide whether it should go direct, through the proxy, or to a block.
Rules are usually evaluated from top to bottom, and evaluation stops at the first match. Put specific conditions first, broad conditions later, and use a default outbound at the end for unmatched traffic. A common baseline is to send private addresses direct, send local domains and IP sets direct, send explicitly proxied domains through the proxy, and route everything else through the default policy. If “proxy all domains” is the first rule, later direct rules will never run.
Choose a domain strategy
The domain strategy in routing determines when the core resolves a domain to an IP before applying IP rules. With AsIs, domain requests are evaluated against domain rules first and are not actively resolved for routing. With IPIfNonMatch, the core resolves the domain only after no domain rule matches, then tries IP rules. With IPOnDemand, resolution may be triggered whenever a later check requires an IP. For a general setup, start with IPIfNonMatch; it supports both domain rules and IP sets, provided the DNS configuration returns stable results.
Active resolution couples routing to DNS. If DNS returns unstable addresses or assigns different regions across paths, IP-rule results may also change. Prefer domain rules for targets that can be expressed with clear domain sets, and rely on IP rules only when the destination address is genuinely needed for the decision. When logs show an unexpected rule result, inspect the original domain, the resolved IP, and the final outbound tag together.
{
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"type": "field",
"ip": ["geoip:private"],
"outboundTag": "direct"
},
{
"type": "field",
"domain": ["geosite:cn"],
"outboundTag": "direct"
},
{
"type": "field",
"ip": ["geoip:cn"],
"outboundTag": "direct"
}
]
}
}
Combine domain, IP, port, and inbound conditions
Different fields within one rule are usually treated as “all must match,” while multiple values within one field are usually treated as “any may match.” For example, a rule containing network: tcp and port: 80,443 handles only TCP on those two ports. Multiple domain sets in an array match when any one set matches. Do not pack unrelated targets into one rule; splitting them into focused rules with clear purposes makes troubleshooting easier.
Inbound tags are useful for assigning different policies to different local entry points. A browser might use a local SOCKS inbound while work software uses another HTTP inbound, with each directed to the proxy or direct outbound. Process rules depend on support from the client, core, and operating system permissions, and behavior varies across platforms, so treat them as a refinement rather than the sole basis for split routing. Port rules work for clearly defined services, but modern applications may switch ports or use QUIC; inferring the application type from ports alone can miss matches.
Build a three-layer rule structure
The first layer handles local targets that should not be sent to a remote proxy, such as loopback, LAN, and private addresses. The second handles business exceptions, such as specified domains that should go direct, domains that require the proxy, and ads or known risky targets that should be blocked. The third defines the default egress. Order each layer from specific to broad. After changing the rules, test three targets covering direct, proxy, and default paths instead of validating only the rule currently under review.
Block rules should remain explainable. If an application fails to start, temporarily disable the block rule to verify it before blaming the server. Be careful with UDP rules: blocking all UDP can affect DNS, real-time communication, or QUIC-based connections. If the goal is only to make a particular domain fall back to TCP, handle it in the relevant application or core transport settings first. For LAN access, check both private-address direct routing and the TUN bypass range.
Use logs to verify rule matches
For verification, clear the logs or mark a time point, then make a single request. Check which inbound received it, which domain or IP was identified, which rule matched, and which outbound was selected. If the logs show only an IP and no domain, the application may have resolved the target itself, so domain rules cannot match directly. Consider TUN domain sniffing, FakeDNS, or reliable IP rules. If the correct rule matches but the connection fails, the problem is in the corresponding outbound or server layer.
The core of routing maintenance is not the number of rules, but whether every rule has an explainable target, a stable data source, and a clear fallback. After a quarterly review or a subscription structure change, check stale domains, duplicate sets, and lower rules that can never match. When some applications work and others fail, first compare whether they enter the same inbound, use the same DNS, and match the same outbound. Then consult the Help Center for the relevant troubleshooting branch.
DNS Configuration Optimization: Align the resolution path with routing decisions
Map the path of a query first
DNS issues are often mistaken for server problems. A domain request may pass through one or more layers: the application’s own resolver, the operating system, the client’s built-in DNS, or a remote resolver. If a browser enables its own encrypted DNS, queries may bypass system settings. After TUN interception, system queries may enter the core; FakeDNS may return a synthetic local address and delay real resolution. Before optimizing, identify who sends the query, which server receives it, and where the result is used for routing.
A basic configuration should follow one primary path: ordinary applications send queries to the system, the client intercepts system queries, and the core selects local or remote DNS based on domain sets, returning results for both connections and routing. If an application resolves domains itself and gives only an IP to the client, the core loses the original domain and domain-based routing becomes less effective. Standardize the application settings, or use sniffing and FakeDNS in a TUN setup to restore the domain association.
Select DNS servers by domain set
DNS splitting and traffic splitting should point in the same direction. Send local domains intended for direct access to a locally reachable DNS server, and send domains intended for the proxy to a remote DNS server reachable through the proxy outbound. This reduces mismatches between DNS results and the actual egress. Do not simply query several servers and choose the fastest response: the fastest response is not necessarily the one that fits the routing intent, and concurrent queries make results less predictable.
{
"dns": {
"queryStrategy": "UseIPv4",
"servers": [
{
"address": "223.5.5.5",
"domains": ["geosite:cn"],
"expectIPs": ["geoip:cn"]
},
{
"address": "https://1.1.1.1/dns-query",
"domains": ["geosite:geolocation-!cn"]
},
"223.5.5.5"
]
}
}
In this example, geosite:cn is assigned to a local DNS server and expectIPs restricts the returned address range. Other clearly non-local domains use encrypted DNS, with the final entry as a fallback for unmatched queries. In practice, choose DNS servers that are reliably reachable from your network rather than keeping example addresses unchanged. If a remote DNS server must be reached through the proxy, also ensure that resolving its own domain or address cannot create a loop.
Choose query strategy and address family
UseIPv4 requests only IPv4 addresses and suits environments where local IPv6 is unavailable or routing is incomplete. UseIPv6 requests only IPv6. UseIP permits both address families. Choose based on the combined support of the local link, proxy outbound, and target service. If any one layer cannot carry IPv6 reliably, forcing IPv6 can produce a domain that resolves but a connection that times out. Conversely, when the network and outbound support it, disabling IPv6 permanently discards a usable path.
Do not judge by whether the system has an IPv6 address. Test local direct access, the proxy outbound, and DNS responses separately. If the logs show an unreachable IPv6 attempt before falling back to IPv4, pages may open slowly; temporarily use UseIPv4 to verify, then complete the IPv6 routing. Do not change the address family and domain splitting at the same time, or you will not know which change helped.
Prevent DNS loops and leak paths
A DNS loop commonly occurs when resolving the DNS server’s own domain requires calling that same DNS server again. Provide a directly usable IP, pin a bootstrap address with hosts, or configure a separate bootstrap resolver. Another loop occurs when the DNS outbound is routed back through the ordinary proxy inbound and triggers DNS again. Assign DNS queries a dedicated outbound tag and handle it early in routing to keep the path one-way.
{
"dns": {
"hosts": {
"resolver.example": "192.0.2.53"
},
"servers": [
{
"address": "https://resolver.example/dns-query",
"skipFallback": true
}
]
}
}
Reserved addresses in examples only illustrate field relationships. Replace them with addresses explicitly provided by the resolver you use. A leak path means the configured path differs from the intended one: if a domain should use remote DNS but the application or another system interface queries it directly, the query has deviated. Check both the client’s DNS logs and system network activity rather than relying only on a web-based test.
Caching, refreshing, and troubleshooting
Old caches may continue affecting results after a DNS change. Reload the client core, close and reopen the test application, and refresh the operating system cache if necessary. On Windows, run ipconfig /flushdns in a terminal. On Linux systems using systemd-resolved, run resolvectl flush-caches. Cache behavior on macOS and Android varies with network state; switching interfaces or reconnecting the client often triggers an update. These commands clear the system cache but do not necessarily clear the browser’s internal cache.
ipconfig /flushdns
resolvectl flush-caches
Keep the troubleshooting order consistent: use an explicit DNS tool to confirm that a response is returned, check the returned address family, see how routing handles that address, and finally inspect the corresponding outbound connection. If only one domain fails, check its domain rule, cache, and server response. If all domains fail while direct IP access works, focus on the DNS inbound, server address, and routing loops. If both domains and IPs fail, return to interception and outbound layers.
TUN Mode: Intercept apps that ignore the system proxy
Decide whether TUN is really needed
The system proxy affects only applications that actively read proxy settings. Command-line tools, some desktop software, games, and programs with their own network stacks may connect directly, leaving no request in the client logs. TUN mode uses a virtual network interface to intercept more system traffic and suits scenarios requiring unified routing, but it also adds variables such as routing tables, DNS hijacking, permissions, and bypass rules. If browsers and common desktop software already work through the system proxy, do not enable TUN merely to make the configuration feel more complete.
Before enabling it, complete the baseline from the previous sections: the server works, routing rules are explainable, and DNS resolves reliably. Disable other software that creates virtual interfaces or changes the default route, record the original system proxy state, and keep a recovery method available. If TUN fails to start, exit the client first so the virtual interface and routing table can recover, then adjust the settings. Do not repeatedly switch between implementations on a leftover interface.
Choose the stack implementation and basic parameters
A client may offer network stack options such as system, gVisor, or mixed. The system stack depends more on operating system capabilities and usually follows a direct performance path. gVisor uses a user-space network stack and behaves differently from the system stack. mixed attempts to combine TCP and UDP handling. No option is best for every environment. Start with the client default and switch one option at a time only when a specific app cannot connect, UDP behaves abnormally, or sleep recovery fails. Keep logs for comparison.
MTU determines the packet size carried by the virtual interface. An MTU that is too large may cause fragmentation or packet loss on complex paths, making small pages work while large requests stall. An MTU that is too small increases packet count and processing overhead. Keep the default without clear evidence. For troubleshooting, lower the MTU gradually and test the same target; do not also change the network stack and DNS. Strict routing can reduce bypassed traffic, but it may affect local network access, so pair it with bypass addresses.
| Platform | Key prerequisites | First checks | Common recovery action |
|---|---|---|---|
| Windows | Permission to create a virtual interface | Administrator privileges, interface, and routing table | Exit the core and re-enable the network interface |
| macOS | Approve network extension permissions | System authorization, DNS, and default route | Disconnect and recreate the interface |
| Android | Permission to create a local virtual network | System authorization and battery restrictions | Disconnect the client and reconnect |
| Linux | TUN and route-management permissions | Device, policy routing, and firewall | Stop the core and remove leftover rules |
Configure bypasses for LAN and reserved addresses
After TUN interception, printers, network storage, router administration pages, or development environments may be sent through the proxy by mistake. Send loopback, private, and link-local addresses direct first, and confirm that UDP needed for LAN discovery is not blocked by a broad rule. Common private ranges include 10.0.0.0/8, 172.16.0.0/12, and 192.168.0.0/16, but enterprise networks may use other internal ranges, so follow the actual routing table.
Bypassing private addresses does not allow LAN devices to access the client’s proxy port. LAN sharing is a separate inbound setting that must be enabled deliberately, with its listening address and firewall scope restricted. For local-only use, keep the proxy inbound bound to the loopback address. If sharing is enabled, confirm that the local network is trusted before defining the access range. TUN route bypasses cannot replace inbound access control.
Handle DNS hijacking and domain identification
Reliable domain-based routing in TUN mode usually requires system DNS queries to be redirected into the core. If connections are intercepted without DNS, an application may obtain an IP outside the system and the core can route only by IP. After enabling DNS hijacking, confirm that queries enter the client’s built-in DNS and prevent the client’s own resolution requests from being hijacked again. Port 53 is the traditional DNS entry point, but applications with built-in encrypted DNS may still bypass it and require coordinated application and routing settings.
Sniffing can recover a target domain from some connections, but it is not reliable for every protocol. After enabling it, check for incorrect destination rewriting, especially with custom certificates, internal domains, or specialized service discovery. If a connection closes immediately after being established, temporarily disable destination override and keep domain identification for comparison. FakeDNS is another way to preserve domain mappings and suits TUN scenarios, but it requires a separate address pool and correct cleanup policy, covered in the next section.
Locate TUN failures by symptom
If the network goes completely offline after enabling TUN, first check that the core started successfully, the virtual interface was created, the default route points where expected, and DNS still has a reachable path. If only LAN access fails, check private-address direct routing and strict routing. If only UDP applications fail, compare the network stack, UDP routing, and server protocol support. If failure appears after waking from sleep, recreate the TUN interface and check for leftover routes. Do not delete the entire client configuration first; TUN failures usually belong to the interception layer.
After verification, test a browser, an app that previously ignored the system proxy, LAN resources, DNS queries, and UDP workloads separately. TUN is stable only when all five paths are explainable. If the goal is merely to proxy one command-line program, set an explicit proxy environment variable for that program; it is easier to maintain than system-wide interception.
FakeDNS: Preserve domain information and defer real resolution
Understand what synthetic addresses do
When FakeDNS receives a domain query, it returns a synthetic IP from a configured pool instead of immediately giving the application the real destination, while storing a mapping between the synthetic IP and the original domain. The application then connects to the synthetic IP. TUN or another transparent interception layer sends that connection back to the core, which looks up the mapping, restores the domain, and selects DNS and an outbound according to the domain rules. Even when an application connects only to an IP, the core can therefore recover the original domain and route more reliably by domain.
A synthetic address is not the address of a remote server and should not be treated by ordinary routing as a public destination. It is only a mapping index within the local interception path. If a request bypasses TUN and goes directly onto the network, the synthetic address cannot be reached. FakeDNS must therefore be paired with an interception method that can capture the subsequent connection. Enabling FakeDNS in the built-in DNS alone does not complete the loop.
Plan an independent, non-conflicting address pool
The address pool must avoid ranges used by the real local network, enterprise intranet, container networks, or existing virtual interfaces. Before configuring it, inspect the system routing table and confirm that the candidate subnet is not occupied by a real route. A pool that is too small causes frequent mapping reclamation under heavy concurrency; one that is too large may conflict with other network plans. Keeping the client default is usually safest. Change it only after confirming a conflict, and then check that TUN routing covers the new range.
{
"dns": {
"servers": [
{
"address": "fakedns",
"domains": ["geosite:geolocation-!cn"]
},
"223.5.5.5"
],
"queryStrategy": "UseIPv4"
},
"fakedns": [
{
"ipPool": "198.18.0.0/15",
"poolSize": 65535
}
]
}
198.18.0.0/15 is commonly used for benchmarking networks, and some clients use it by default for synthetic addresses, but still check whether the local network already routes that range. poolSize controls the number of available mappings and should not exceed the pool’s actual capacity. Configuration fields vary by core family and by how the client generates them. In a graphical interface, let the client generate the structure first, then inspect the final core configuration instead of pasting the entire example into an incompatible layer.
Decide which domains use FakeDNS
Not every query needs a synthetic address. Local domains, LAN services, printer discovery, and tools that require a real IP returned to the application should usually continue using ordinary DNS. Public targets intended for domain-based proxying are better candidates for FakeDNS. Start with a clearly defined non-local domain set and expand it only after stability is confirmed. Sending every query through FakeDNS may give local services unusable synthetic results.
Exclusions should cover LAN suffixes, development domains, and diagnostic tools that depend on real addresses. An application that displays DNS results to users, writes them into configuration, or passes them to another device should also not receive machine-local synthetic IPs. FakeDNS preserves domain association during transparent interception; it is not a general DNS accelerator, and synthetic results should not be propagated to other LAN devices.
Coordinate sniffing, routing, and real resolution
After FakeDNS restores the original domain, routing should select the egress by domain rule, and real DNS should follow a path consistent with that egress. For direct traffic, use a resolver suited to the direct link; for proxied traffic, use the resolver assigned to the proxy path. Otherwise, restoring the domain may still produce an address unsuitable for the selected egress. Logs should show the synthetic mapping, domain match, and real destination connection as one continuous sequence.
Sniffing and FakeDNS can work together, but their responsibilities differ. FakeDNS restores domains through query mappings; sniffing identifies domains from connection content. When both are enabled, define clearly whether destination override is allowed. If the same connection produces conflicting domain decisions, first disable sniffing override and keep FakeDNS for comparison. If an application never makes an interceptable DNS query, FakeDNS cannot create a mapping, while sniffing may still provide information.
Identify cache and mapping expiration
Applications, the system, and the client may all cache synthetic results. After changing the address pool or disabling FakeDNS, an old synthetic IP may continue to be used, causing some domains to fail. Disconnect TUN, reload the core, flush the system DNS cache, restart the test application, and reconnect. Do not repeatedly change the pool while connections remain active, or old mappings and new routing may coexist briefly.
If failures begin only after a long runtime, check pool capacity, mapping reclamation, and the application’s DNS cache lifetime. If a specific domain works the first time but fails later, compare changes in real DNS responses and check whether an old connection reused an expired mapping. If every synthetic address fails, focus on whether TUN intercepts that subnet rather than changing the remote server.
Final verification should cover four targets: an ordinary public domain, a clearly direct domain, a LAN domain, and an application with its own resolver. A public target should receive a mapping and follow domain routing; direct and LAN targets should receive real addresses under the exclusion policy; an app with its own resolver must be checked for entry into the interception path. FakeDNS improves domain routing only when all four results match the design instead of adding another opaque layer.
Custom Outbounds: Labels, chained forwarding, and final troubleshooting
Define outbound roles and labels first
An outbound is the final destination of a routing rule. A minimal configuration usually has three roles: proxy, direct, and block, using the stable labels proxy, direct, and block. Custom outbounds are useful for a dedicated direct interface, a separate DNS outbound, or chained forwarding, but every additional outbound requires maintaining its label, routing references, and fallback. Labels are case-sensitive. After renaming one, search all rules to prevent routing from pointing to the old name.
Graphical clients usually generate the primary proxy outbound from the current server. Direct edits to that generated object may be overwritten when switching servers or updating subscriptions, so custom sections should go in an additional configuration area, preset profile, or custom outbound section supported by the client. Confirm the merge order first: does a same-named field override, append, or fail? If uncertain, export the final core configuration and inspect the actual result rather than relying on the input fragment shown in the interface.
{
"outbounds": [
{
"tag": "direct",
"protocol": "freedom",
"settings": {
"domainStrategy": "UseIP"
}
},
{
"tag": "block",
"protocol": "blackhole",
"settings": {
"response": {
"type": "none"
}
}
}
]
}
Assign an address family or interface to the direct outbound
A multi-homed device may connect through wired, wireless, virtual, and enterprise networks at the same time. By default, direct traffic uses the interface selected by the system route. When supported by the core, a custom direct outbound can specify a source address or address family so a class of traffic stays on a particular local interface. Confirm that the address will persist before configuring it; dynamically assigned addresses may fail after sleep, reconnection, or a network change. If the goal is simply LAN access, rely on system routing and private-address direct rules instead of forcing an interface.
The address-family setting must agree with the DNS query strategy. If the direct outbound allows only IPv4 but DNS returns IPv6, the connection still fails. A dual-stack proxy outbound does not imply that local direct access supports both families. During troubleshooting, record the DNS result, routing tag, and actual dial address separately. On multi-homed systems, also check the priority of TUN-created routes to prevent custom direct traffic from re-entering TUN and forming a loop.
Understand the limits of chained forwarding
Chained forwarding lets one proxy outbound establish its connection through another outbound. It can serve a defined network topology or an entry restriction, but it adds handshake layers, latency, and failure points, so it should not replace server filtering. Verify the upstream and final outbounds independently before connecting them. A failure in DNS, address family, UDP support, or transport at any layer will appear as a failed final connection.
The chain must be loop-free. If outbound A uses B, B must not use A. A DNS outbound must not depend on a proxy that ultimately needs that same DNS server for resolution. Use clear labels such as proxy-entry and proxy-exit for each layer so logs reveal where the failure occurs. The default route should point only to the final business outbound; an upstream outbound is normally called by the forwarding relationship and does not need to be matched directly by a broad rule.
Create a dedicated DNS outbound
When the core supports a DNS outbound, internal DNS queries can be sent along a specified path through a dedicated tag. This lets routing separate DNS traffic from ordinary connections and reduces loops. A typical structure is for the built-in DNS to generate queries, the DNS outbound to send them, and routing to direct the relevant inbound or protocol to dns-out first. If the remote resolver requires the proxy, make dns-out use an explicit proxy path instead of relying on the default rule to guess.
{
"outbounds": [
{
"tag": "dns-out",
"protocol": "dns",
"settings": {
"address": "1.1.1.1",
"port": 53,
"network": "tcp"
}
}
],
"routing": {
"rules": [
{
"type": "field",
"inboundTag": ["dns-in"],
"outboundTag": "dns-out"
}
]
}
}
This example illustrates label relationships; not every client generates a DNS outbound from the same fields. With encrypted DNS, configure the address, port, and transport according to the core’s support. Verify that each query passes through exactly one inbound and one outbound without returning to the ordinary DNS entry. If the same domain repeats continuously in the logs, suspect a resolution loop first.
Troubleshoot from the layers outward
When a complex configuration fails, inspect each layer outward from the request entry. First confirm that application traffic enters through the system proxy or TUN. Second, confirm that DNS returns a usable result while preserving the domain. Third, confirm that routing selects the expected tag. Fourth, confirm that the tagged outbound exists and has valid parameters. Only then inspect the remote connection. Each step needs log evidence. Replacing the server before checking the entry and routing layers often changes the symptom only temporarily.
Narrow errors by scope. If every application fails, the issue is likely core startup, interception, or the default outbound. If one application fails, compare its proxy method, protocol, and DNS behavior. If one domain fails, check its domain rule, cache, and real resolution. If only UDP fails, check the network stack, routing, and outbound capability. If only LAN fails, check private addresses and TUN bypasses. Mapping symptoms to configuration layers is more reliable than memorizing a single “fix command.”
Pre-release checklist
- Keep a minimal working configuration and one stable fallback server.
- Confirm that subscription updates do not overwrite local DNS, routing, or custom outbounds.
- Confirm that every routing rule references an existing outbound label and that the default rule is last.
- Verify direct, proxy, block, DNS, and LAN paths separately.
- After enabling TUN, test apps that ignore the system proxy and check virtual-interface recovery.
- After enabling FakeDNS, check address-pool conflicts, mapping recovery, and excluded domains.
- Return logging to the normal level, export the final configuration, and state its purpose.
Do not treat the finished configuration as permanent. Subscription names, network interfaces, system permissions, and business domains change, so rerun the baseline tests when behavior changes noticeably. If you need to switch clients, read the v2rayN, v2rayNG, and v2flyNG comparison first. To reinstall, visit the client download page. For specific log errors, follow the runtime log troubleshooting steps. Layered configuration, stable labels, and reversible changes matter more than continually adding rules.