JSON · routing · dns · policy

V2Ray Configuration Reference Guide

Look up configuration fields to understand local listeners, outbound selection, intended behavior, boundaries, and validation.

New to V2Ray? Start with the Getting Started Guide to import a configuration, choose a mode, and test your connection. This reference is for readers who need to understand core JSON, inspect routing, or maintain custom configurations; it is not a replacement for the client’s quick-start workflow.

JSON Structure and Configuration Boundaries

Check where the configuration comes from before changing fields

A V2Ray configuration is not just a list of servers. It describes how traffic enters the process, matches rules, and leaves. The top-level object commonly includes log, inbounds, outbounds, routing, dns, and policy. Not every section is required; omitted sections follow the core’s defaults. Before looking up a field, confirm whether Xray or V2Fly is running and whether the client regenerates the configuration at startup. Otherwise, you may be editing a file that is never loaded.

Desktop users often start with v2rayN. After importing a subscription, they select a server, system proxy, and routing mode in the interface, and the client converts those choices into a core configuration. The subscription stores connection details, the interface stores user preferences, and the JSON in the runtime directory may be only generated output. Each has a different role. To troubleshoot, you can inspect the generated file, but make lasting changes through settings supported by the interface or its custom configuration options. Don’t mistake a temporary edit for a saved client setting, or repeatedly edit the same file without understanding what overwrites it.

A Minimal Local Direct-Connection Baseline

Here is a complete starter configuration: it exposes a SOCKS inbound on the local loopback address, sends incoming connections through the freedom outbound, and sets the log level to warning. It does not connect to any remote proxy. Use it to check whether the core starts, the local port is available, and a test application is actually using the inbound. The port is only an example; if another client is using it, stop the conflicting process or choose a free port. A working direct-connection baseline confirms only that the local path works—not that a remote configuration is correct.

{
  "log": {
    "loglevel": "warning"
  },
  "inbounds": [
    {
      "tag": "socks-local",
      "listen": "127.0.0.1",
      "port": 10808,
      "protocol": "socks",
      "settings": {
        "auth": "noauth",
        "udp": true
      }
    }
  ],
  "outbounds": [
    {
      "tag": "direct",
      "protocol": "freedom",
      "settings": {}
    }
  ]
}

Standard JSON requires double quotes around property names and strings, no trailing commas after the last item in an object or array, and Boolean values written as true or false. Numeric ports do not need quotes. Some core tools can read extended formats with comments, but editors, client importers, and other tools may not. For easier copying and troubleshooting, all examples here use standard JSON with no comments inside code blocks. Keeping explanations outside the code avoids parser differences and makes it easier to replace sections.

How Objects, Arrays, and Tags Work Together

Both inbounds and outbounds are arrays: a process can listen on multiple inbounds and provide multiple outbounds, with each array entry represented by an object. A tag is an internal reference name, not a protocol name, and it does not create functionality by itself. Naming an outbound proxy does not give it a remote address. A routing rule’s outboundTag must match an actual outbound, including capitalization and spelling. Use short, consistent, descriptive tags.

Make configuration changes in small, testable steps: save a working baseline, add one outbound, then add a routing rule, and finally adjust DNS or policies. Record the fields affected, the expected result, and how to roll back each change. Array order can affect the default outbound and routing matches, so don’t reorder entries just for presentation. If you only need the client to work normally, stick with its generated configuration. Use manual configuration only when you need behavior the interface cannot provide, rather than taking on the complexity of maintaining both client state and core files.

inbounds: Local Listeners and Traffic Entry Points

What listen, port, and protocol control

An inbound accepts connections from applications and passes them to the core. listen sets the local address to bind, port sets the listening port, and protocol determines the request format it accepts. All three matter: connecting to the right port with the wrong protocol still won’t produce a valid request. A SOCKS inbound cannot be entered as a regular HTTP proxy, or vice versa. When troubleshooting, compare the listener protocol shown by the client with the application’s proxy type instead of checking only that the port numbers match.

For applications on the same device, the listener is usually bound to 127.0.0.1. This address accepts loopback connections only; it is not a LAN address and does not automatically include the IPv6 loopback address. Binding to 0.0.0.0 generally means listening on all IPv4 network interfaces. Whether other devices can connect also depends on the firewall and network isolation. Before widening the listener scope, decide which devices need access, what authentication to use, and whether another listener process might remain after the client exits. Allowing LAN access changes the security boundary; it is not just a connection tweak.

SOCKS and HTTP Inbound Examples

This snippet shows two separate inbounds on different ports, each with a tag for use in routing rules. In SOCKS, udp allows the inbound to handle SOCKS UDP requests, but the application must use that mechanism and the outbound and network path must also support UDP. The HTTP inbound is for applications that use an HTTP proxy. Having both inbounds does not mean every application or type of traffic will be captured automatically. To use this snippet with the baseline in Chapter 1, replace the entire inbounds array rather than adding another top-level field with the same name.

{
  "inbounds": [
    {
      "tag": "socks-local",
      "listen": "127.0.0.1",
      "port": 10808,
      "protocol": "socks",
      "settings": {
        "auth": "noauth",
        "udp": true
      }
    },
    {
      "tag": "http-local",
      "listen": "127.0.0.1",
      "port": 10809,
      "protocol": "http",
      "settings": {}
    }
  ]
}

Two ordinary listener instances generally cannot bind to the same address and port at the same time. If binding fails, check whether the client was started twice, a test core is still running, or an old process did not exit cleanly. Don’t change the application’s proxy port without updating the inbound, or change the inbound while continuing to use the old system proxy port. In desktop v2rayN, the local listener port may be linked to other interface settings. Check the generated configuration and logs for the actual values; example ports are not universal defaults.

Sniffing and the Original Destination

An inbound can also include sniffing, which identifies information such as domain names from the initial data of some protocols to help with domain-based routing. It does not decrypt traffic, identify every connection, or replace correct DNS configuration. Some connections contain only an IP address, while the destination information in other protocols may not be visible, so rules can receive different inputs. If you want sniffed information to affect routing without rewriting the actual destination, check how the current core supports and defines the relevant options. Don’t blindly copy advanced sniffing fields between different cores.

To check whether an inbound works, configure its address and protocol in an application that explicitly supports manual proxy settings, send a separate test request, and look for the corresponding inbound tag in the logs. If no entry appears, check whether the application bypasses the proxy, uses different network settings, or whether the log level is high enough to show connections. A system proxy is just a way to make settings available to applications; it does not force traffic through the proxy. For basic setup and traffic coverage, return to the Getting Started Guide. For connection failures, work through the checks in Troubleshooting.

outbounds: Proxy Protocols and Remote Settings

Create an outbound before referencing it in rules

An outbound describes how the core sends accepted traffic to its destination. freedom connects directly to the destination; blackhole drops or rejects traffic; remote proxy protocols require additional server and account details. An outbound being present in the array does not mean it will be used. That depends on the routing result and default behavior. In common setups, connections that match no rule use the first outbound, so changing array order can change where traffic goes. Document the default outbound instead of assuming behavior from a tag’s name.

This snippet includes only direct and blocking outbounds. Combine it with the basic inbound to practice routing references; it does not provide a remote connection. settings is protocol-specific, and each protocol accepts different fields. Similar-looking top-level fields do not make the inner parameters interchangeable. When changing a remote protocol object to freedom, remove the old protocol’s parameters as well. This keeps the configuration readable and avoids suggesting that the core still uses those account details.

{
  "outbounds": [
    {
      "tag": "direct",
      "protocol": "freedom",
      "settings": {}
    },
    {
      "tag": "block",
      "protocol": "blackhole",
      "settings": {}
    }
  ]
}

Keep Connection Details, Transport, and Security Layers Separate

A remote outbound usually contains three types of information: the server address and port, protocol credentials, and transport and security settings. VMess, VLESS, and Trojan use different credential structures. Switching between TCP, WebSocket, and other transports is not as simple as changing a name. TLS is a separate layer involving the server name and certificate verification. A client maps some of these details when importing a link; manual configuration requires checking the complete combination. A field that looks right on its own may still conflict with the rest of the remote setup.

Setting layerPurposeWhat to check
Protocol settingsRemote address, account, and protocol optionsMatch the service configuration exactly
streamSettingsTransport and security layerEnsure transport, path, and security settings are compatible
Outbound tagReferenced by routing rulesUse an exact tag match
Array orderAffects default outbound selectionCheck that the first outbound is the intended default

The server address can be a domain or an IP, but the connection address and the server name used for TLS verification are not necessarily the same. If the address is a domain, DNS resolution is also part of the connection path, so a remote connection failure may be caused by DNS rather than incorrect credentials. For certificate or handshake errors, check the system clock, server name, certificate chain, and transport settings. Don’t disable certificate verification as a first step. Skipping verification changes the security boundary and can hide an incorrect address. Keep verification enabled and fix the configuration to distinguish service failures from local misconfiguration.

Core Compatibility Determines Whether Configurations Can Be Migrated

Xray and V2Fly share some configuration conventions, but not every protocol feature, transport field, or supported value is compatible. For connection details that use specific security mechanisms or extensions, confirm the running core supports them before importing or customizing the configuration. A client’s name alone does not tell you which core runs at startup: check the selection and logs in v2rayN. v2rayNG primarily uses Xray, while v2flyNG is an Android alternative for V2Fly. When migrating between cores, test one outbound first instead of moving the entire routing setup and advanced features at once.

Subscriptions also introduce configuration lifecycle issues. Updating a subscription may replace server parameters without preserving manual changes to the underlying objects. The client may also regenerate outbound tags based on the current selection. If you need to reference a fixed tag over time, use a custom configuration method explicitly supported by the client and check the generated output after every update. Choose an installer in the Download Center, or read Client Choice to compare the three clients. This guide does not provide remote service access; a connection still depends on valid service settings and network reachability.

routing: Match Order and Routing Rules

Rules are checked in order; they are not sorted by specificity

Routing selects an outbound for each connection. Common field-based rules go in the routing.rules array and are checked in order. The core applies the action for the first match; it does not collect all matching rules and choose the “most specific” one. Put clear exceptions before broader rules. If an earlier rule matches all TCP and UDP traffic, a later domain rule will never get a chance to select an outbound, even if it is correct. To troubleshoot routing, check rule order first, then conditions, and only then whether a data file is missing entries.

Multiple candidates within the same field usually mean “match any,” as with a domain array where any listed domain can match. Different types of conditions in one rule usually apply together. For example, including an inbound tag, domain, and port means the connection must meet all of those conditions, not just one. Combining three independent needs in one rule can unexpectedly narrow the match. For independent exceptions, separate rules are easier to test and make it clearer which rule is taking effect.

A Practice Example Without Geo Data

Use the rules below with the direct and blocking outbounds from the previous chapters. The first blocks the reserved example domain and its subdomains; the next sends connections from the SOCKS inbound directly. All other traffic follows the default outbound. Here, domain: matches a domain and its subdomains, while inboundTag limits the rule to an inbound. This example demonstrates references and rule order; it is not a recommended real-world routing list. Test with a known target and check the logs to confirm the routing result. A page loading successfully does not tell you which rule matched.

{
  "routing": {
    "domainStrategy": "AsIs",
    "rules": [
      {
        "type": "field",
        "domain": [
          "domain:example.org"
        ],
        "outboundTag": "block"
      },
      {
        "type": "field",
        "inboundTag": [
          "socks-local"
        ],
        "outboundTag": "direct"
      }
    ]
  }
}

Use full: for an exact domain match, domain: for a domain and its subdomains, and regex only when complex matching is genuinely needed. Plain-text matching may cover more than you expect, so prefer clear, explicit syntax. IP rules can use individual addresses or CIDR ranges, but private, loopback, and link-local addresses have different meanings; they are not all interchangeable “local addresses.” The target IP in a rule is not necessarily the only address returned by the initial lookup. The resolution stage for a domain connection affects which information is available for matching.

domainStrategy and the Limits of Geo Data

AsIs tries to match the target in its current form without resolving a domain to an IP for routing. IPIfNonMatch tries to resolve a domain if it did not match at the domain stage, then uses the result in later checks. IPOnDemand resolves when routing needs IP information. These settings control resolution during routing; they are not a global DNS switch and do not determine which address family each outbound ultimately uses. Before choosing one, ask whether your rules depend on domains or IPs, and whether additional lookups are acceptable to match IP rules.

geosite and geoip reference data files; the core does not generate these classifications on its own. Missing files, incorrect paths, or nonexistent category names can cause loading failures or unexpected behavior. The data also changes, so a category is not a permanently accurate boundary for your needs. For important destinations, use explicit rules whose behavior is clear, and decide whether they belong before or after category-based rules. For local services, account for OS routing and firewall rules too. Core domain rules alone cannot solve every network access issue.

Test routing with one target, one expected outbound, and one relevant log entry. Temporarily remove unrelated rules, confirm whether the target is a domain or an IP, then restore data-based and more complex conditions. For a fuller split-routing example, see V2Ray Routing Rules in Practice. Before importing existing rules, check whether their tag references, order, and data dependencies fit your configuration. Copying an entire rule set often just buries an easy-to-diagnose problem under more conditions.

dns: Resolution Paths and Domain Information

First identify what is making the DNS request

DNS issues are often summarized as “the domain won’t load,” but a connection may involve DNS resolution by the application, the operating system, the core’s built-in DNS, or the remote server. These may not use the same settings. If an application resolves a domain to an IP before sending it to a SOCKS inbound, the core sees a different starting point than when it receives the domain itself. Adding a top-level dns section does not make the operating system and every application use that resolver, or automatically capture all requests to external DNS servers.

Built-in DNS can provide results for core features that need resolution, such as some routing checks and direct outbound connections. Whether it is used still depends on the relevant module’s policy and the core implementation. When troubleshooting, note where the domain was first resolved, which outbound carried the request, and where the result was ultimately used. Changing one DNS server without tracing the request path may bring a site back temporarily, but won’t explain why another application still fails or prevent the same issue from returning after further changes.

DNS Servers, Static Mappings, and Address Families

Here is a standard JSON snippet that adds a static mapping for a reserved example domain and lists DNS servers with an IPv4 query strategy. It illustrates the field structure; it is not a recommended server list for every network. Your network may restrict certain DNS transports, and a server may not be reachable from your current path. Use static mappings only when you know the destination address. If a service address changes frequently, pinning it can leave you connecting to an old address, cause certificate errors, or break regional load balancing.

{
  "dns": {
    "hosts": {
      "example.org": "93.184.215.14"
    },
    "servers": [
      "1.1.1.1",
      "8.8.8.8"
    ],
    "queryStrategy": "UseIPv4"
  }
}

queryStrategy controls which address family is used for query results. Common values include UseIP, UseIPv4, and UseIPv6; check support in the running core. Choosing IPv4 can help isolate some IPv6 path issues, but it is not a universal fix for timeouts. If a service has only one type of address record, restricting the family may leave no usable result. Conversely, receiving an IPv6 address does not mean the local device has a working IPv6 route or a suitable outbound. DNS resolution and establishing a connection are separate stages.

Domain-Specific DNS and Circular Dependencies

The servers array can contain server objects with domain conditions and expected IP ranges to specify more precise DNS behavior. Domain conditions here select a DNS server; they do not select an outbound as routing.rules does. How the resolver’s network connection is sent also depends on its transport and the core implementation. Some local and standard modes route traffic differently. Before configuring encrypted DNS, confirm what the relevant fields actually mean in your core; don’t assume every DNS request automatically uses the proxy outbound.

Avoid circular dependencies in bootstrap resolution: the remote server address needs to be resolved, but the DNS resolver itself is accessible only through that remote connection, which has not yet been established. A similar problem can arise with encrypted DNS addresses specified as domains. Make sure the bootstrap step can work independently, and establish how the remote server’s domain gets an address before adding a more complex resolution path. Don’t hide the cycle by disabling security checks or pinning an arbitrary server address. Trace the dependency chain and check the roles of system DNS, core DNS, and outbound connections.

FakeDNS uses virtual addresses mapped to domains so later stages can recover the domain name. It usually requires the inbound, resolution flow, and core features to work together. Adding a setting or copying a snippet alone does not give a regular system proxy full traffic capture. When leaving a related mode, also watch for virtual addresses left in application or system caches. For more on its limits and use cases, see FakeDNS: How It Works and When to Use It. Start troubleshooting with a simple resolution path, then consider this mechanism once the basics are stable.

policy, log, and stats: Runtime Behavior

policy controls connection behavior, not outbound selection

policy is commonly used to set connection handshake and idle timeouts, half-close behavior, and traffic statistics. It does not replace routing or improve connection quality just because you add a few numbers. Keys in levels represent user levels and correspond to level information on protocol user objects. In common setups, the default level is used when none is specified. Protocols provide different user information, so don’t assume every inbound can be measured the same way. Before changing a policy, confirm which level the connection actually uses; otherwise, you may edit settings that are never applied.

This snippet explicitly sets common timeout values for the default level. handshake is the time allowed for a handshake; connIdle applies to idle connections; uplinkOnly and downlinkOnly control how long one direction stays open after the other has ended. Values are in seconds. The example explains the structure; it does not mean you should replace all existing client defaults. If things work, keeping client-adjusted defaults is usually easier to maintain than blindly shortening timeouts.

{
  "policy": {
    "levels": {
      "0": {
        "handshake": 4,
        "connIdle": 300,
        "uplinkOnly": 2,
        "downlinkOnly": 5
      }
    },
    "system": {
      "statsInboundUplink": false,
      "statsInboundDownlink": false
    }
  },
  "log": {
    "loglevel": "warning"
  }
}

If the handshake timeout is too short, network jitter or a multi-layer transport setup may not finish before the connection is closed. A short idle timeout can disrupt long-lived connections, push notifications, or intermittent transfers; an excessively long one can keep unused connections open. Some applications use their own heartbeats and retries, so application behavior also affects the results. Adjust policies to address a reproducible problem and compare logs and connection stages before and after. One successful attempt does not prove a change worked, and a timeout value is not a measure of service response speed.

Log Levels and Output Paths

Common loglevel values are debug, info, warning, error, and none. Debug logs are more detailed, but increase log volume and may expose more private information. There’s no need to keep the most detailed logs enabled during normal use. Without a file path, output may go to the console or be captured by the client. When setting access and error log paths, ensure the running user can write to them and know which working directory relative paths use. If no new content appears in a file, there may be no connection—or you may be checking an old path or a different log.

Access and error logs serve different purposes: access logs help show request destinations and outbounds, while error logs help pinpoint where DNS, connection, or handshake failures occur. When reviewing logs, first match the time range to the same test, then check the inbound tag, destination address, and error chain. A final timeout may follow an earlier DNS failure, so don’t look at only the last line. Logs may contain domains, addresses, user identifiers, or local paths. Remove sensitive information before sharing and retain only what is needed to understand the flow; don’t publish complete runtime logs.

Statistics Toggles and the Management API

Top-level stats and the statistics toggles in policy control different parts of data collection: the former enables statistics modules, while the latter determines which metrics are collected. Adding an empty stats object does not create an accessible dashboard. Reading statistics usually also requires a management API, service definitions, and isolated listeners. This guide does not recommend exposing a management interface just to troubleshoot, or treating statistics as a network performance verdict. If the client already displays traffic, prefer its existing integration rather than setting up another interface with unclear boundaries.

If a connection works but drops after a while, first distinguish between the application closing it, the remote end closing it, an idle policy taking effect, and a network change. Then consider adjusting policy. If the handshake fails every time, changing idle settings won’t fix the root cause. For a more complete guide to reading logs, see How to Read V2Ray Runtime Logs. Once you’ve identified the issue, restore an appropriate everyday log level, remove debug files you no longer need, and document any necessary policy changes with your configuration backup.

Client Settings vs. Core JSON

v2rayN: Interface State Is Not File State

v2rayN is the recommended starting point for desktop users, but a graphical client does not keep every setting in a single JSON file. The server list, subscription URLs, window preferences, routing templates, and core runtime configuration may be stored separately. When you start the client, it combines the current selections into a configuration the core can load. Stopping and restarting, switching servers, or updating a subscription can regenerate that output. Before editing a file, determine whether it is a lasting source or a temporary artifact. Don’t rely on an unidentified file as your only backup or edit it while the core is running and guess whether the changes took effect.

System proxy settings are a convention between the operating system and applications; core JSON describes the process’s own listeners and forwarding behavior. Both are needed for common desktop workflows. Clearing the system proxy does not necessarily stop the core, and stopping the core may not immediately clear stale proxy settings in the OS. If an application keeps sending requests to a closed local port, it can look as if all connectivity is down. Check the system proxy and process state separately before and after quitting. Don’t blame every refused connection on the remote service or try to fix stale settings by running multiple clients at once.

Configuration Differences Across Platforms and Cores

v2rayN can be used on Windows, macOS, and Linux, but permissions, runtime directories, system proxy integration, and traffic-capture mechanisms differ. Path syntax, write access to the configuration directory, and the identity running the service can all affect what is loaded. Android users generally choose v2rayNG; for V2Fly-based configurations, v2flyNG is another option. Android’s system traffic-capture permission is not the same as a desktop system proxy. When migrating, keep the connection details and verify traffic capture settings for the new platform instead of copying the entire working directory and expecting every path and permission to carry over.

ClientSupported platformsWhat to check in the configuration
v2rayNWindows / macOS / LinuxRunning core, generated configuration, and system proxy state
v2rayNGAndroidXray field support, system permissions, and app traffic capture
v2flyNGAndroidV2Fly field support and import format

JSON files can still use entirely different configuration models. v2rayN can run different cores, while this guide’s inbounds, outbounds, and routing examples follow common V2Fly / Xray structures. They cannot be applied directly to sing-box configuration. A file extension alone does not establish compatibility. If a field is rejected, first check which core is running, then whether the import expects a full configuration, a server object, or a client-specific format. Don’t keep patching the wrong format.

TUN and System Proxy Are Not Interchangeable With a Boolean

TUN usually requires a virtual network interface, routing changes, and the necessary permissions. It may also depend on a separate traffic-capture component or a different core. Selecting “Enable TUN” in a client does not mean adding a field with the same name to the top level of this guide’s basic JSON will have the same effect. System proxy settings have a clearer scope but depend on applications using them. TUN captures more traffic, but also requires careful handling of local networks, DNS, and outbound loops. When switching modes, enable one clear traffic-capture path at a time and check that the remote connection itself is not sent back through the inbound.

Manage custom full configurations separately from regular subscription use. A full custom configuration typically requires you to maintain inbounds, outbounds, rules, and data dependencies yourself. With a subscription, the client generates configuration from the subscription and interface settings. Successful import only means the format was accepted; it does not prove that every field took effect. If the client offers a configuration preview or runtime logs, use the loaded result as evidence. Without clear merge instructions, don’t assume a custom fragment is automatically inserted in the right place. Keeping one recoverable, working configuration is more reliable than maintaining multiple temporary files that overwrite one another.

To choose a desktop interface, see v2rayN Desktop vs. WPF Edition and decide based on your operating system and interface preferences—not on assumptions that UI framework differences imply different protocol capabilities. Choose an installer for your platform in the Download Center, then follow the Getting Started Guide for initial setup. Introduce custom core files only after confirming the interface cannot meet your needs. Check that they persist after subscription updates, mode changes, and restarts so the next run uses the intended settings.

Configuration Validation, Log Analysis, and Recovery

Validate syntax and runtime behavior separately

Start troubleshooting with the simplest checks. First, confirm the file is valid standard JSON, with balanced brackets, correct commas, and properly escaped strings. Next, confirm the fields are supported by the current core. Then check tag references, data files, listener ports, and path permissions. Only after that should you test a real connection. Passing syntax checks means only that the file can be parsed—not that a remote service is reachable or routing behaves as expected. A direct-connection configuration with no remote outbound can be perfectly valid, so “the core starts” and “a target uses the intended outbound” must be tested separately.

When running a core manually, use its configuration test mode instead of leaving it listening. The commands below are for locally installed Xray and V2Ray executables. The filename config.json must point to the configuration you actually want to check. Run the command from the right working directory or use the correct executable path. Command-line options can vary across builds; if an option is unrecognized, check the program’s built-in help. Users of graphical clients should rely on the logs and configuration checks they provide; there is no need to set up a separate background process just to follow this guide.

xray run -test -config config.json

v2ray test -c config.json

After the configuration passes testing, stop any conflicting listener before starting the target configuration. Choose an application that clearly supports proxy settings, configure only the inbound needed for this test, send one request, and note the time. With the direct-connection baseline from Chapter 1, you are testing the local inbound—not a remote proxy. Next add a remote outbound with verified settings, then restore routing and DNS. Each stage adds only one major variable, so if something fails, you can narrow it down without guessing among the inbound, DNS, and remote connection at once.

Match the symptom to the layer to investigate

If the core won’t start, first check for parsing errors, unsupported fields, occupied ports, and missing data files. If an application reports that the local connection was refused, check the listener address, port, and process state. If the core receives a request but reports a DNS failure, trace the DNS request path. If the remote handshake fails, check the address, system clock, protocol credentials, and transport security settings. A timeout alone doesn’t identify the failing layer. Follow the logs backward to find the last successful stage and the first clear failure.

SymptomCheck firstWhat to look for next
Process exits on startupJSON, supported fields, and file pathsSpecific field or filename in the startup error
Local connection refusedProcess, listener address, and portWhether the expected inbound is listening
DNS errorDNS server and bootstrap dependenciesWhich layer is resolving the domain
Routing result is unexpectedRule order, target format, and tagsOutbound shown for the request

Avoid application caches interfering with tests. Existing connections may reuse old channels, domain caches may retain previous results, and a running application may not immediately pick up changes to the system proxy. If necessary, close relevant connections or restart the test application, then repeat the same request. Don’t clear every setting at once, or you’ll lose a useful comparison with the original failure. Network changes can also affect reachability and DNS paths, so record the network used for each test. Only results that recur under the same conditions are useful for determining whether a configuration change worked.

Keep a rollback point instead of piling on patches

Whenever a stage is confirmed to work, save the corresponding configuration and a brief note listing the running core, inbound port, default outbound, and required files. Treat backups containing subscription URLs or account details as sensitive; don’t include them in public pages or shared records. When a new issue arises, return to the latest rollback point and reapply changes one at a time. Don’t keep adding exception rules and timeout values to a failing configuration. Once things work again, remove patches shown to be ineffective so future maintainers don’t mistake temporary experiments for requirements.

Finally, check that the configuration persists: stop and restart the client, confirm that subscription updates or mode changes have not overwritten necessary settings, then test the same target again. After troubleshooting, restore an appropriate log level, undo any temporary widening of the listener scope, and clear system proxy settings you no longer use. If the issue remains unresolved, review Troubleshooting with a sanitized error excerpt and minimal reproduction steps. If you only need to repeat the basic setup, return to the Getting Started Guide; the optional fields in this reference are not all required.

Download a Client