JSON Manual · Systematic Reference

V2Ray JSON Configuration File
Structure and Field Reference

Start with the top-level object, then review inbounds, outbounds, routing, dns and policy in order. This page covers field meanings, relationships and troubleshooting boundaries; for importing a subscription and connecting for the first time, see the Getting Started guide.

FormatJSON Core scopeV2Fly / Xray Clientsv2rayN / v2rayNG / v2flyNG
01 · CONFIG

V2Ray JSON Structure Overview and Reading Order

Distinguish core configuration from client settings first

A V2Ray configuration file is a JSON object. After startup, the core reads the top-level fields and combines inbound listeners, outbound connections, routing decisions, domain resolution and connection policies into a processing chain. It does not execute fields line by line in the order they appear in the file, so placing routing before inbounds does not change the runtime result. Traffic direction is determined by references between fields, especially tag, inboundTag, outboundTag and balancerTag.

v2rayN, v2rayNG and v2flyNG each have their own interface settings and data storage. Subscription groups, system proxy toggles and per-app settings shown by the client may not appear unchanged in the core JSON. When debugging on desktop, first confirm that you are viewing the configuration actually loaded for this startup, not an old backup or the original subscription. After the client regenerates the configuration, manual content written directly to the runtime file may be replaced. Rules that must persist should preferably be entered through the client’s custom routing, DNS or advanced configuration options.

Common top-level fields

Field Type Purpose Main relationships
log Object Defines access logs, error logs and log levels Troubleshooting
inbounds Array Accepts connections from local applications or network interfaces routing.inboundTag
outbounds Array Defines how the connection is ultimately handled routing.outboundTag
routing Object Selects an outbound by domain, address, port, protocol and source Inbound and outbound tags
dns Object Defines the core’s internal domain-resolution behavior routing.domainStrategy
policy Object Defines connection timeouts, statistics switches and system-level policies User level and stats
stats Object Enables the core statistics module Statistics switches in policy

A minimal configuration does not mean there is only one server object. A complete processing path needs at least one inbound and one outbound. The inbound determines how an application hands a request to the core; the outbound determines how the core handles it. Routing, DNS and policy can be omitted temporarily, in which case the core uses its defaults. Once routing rules are added, every referenced tag must actually exist. Tags are case-sensitive: proxy and Proxy are different values.

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

This example listens for SOCKS traffic only on the local loopback address and sends everything to the freedom outbound. It is useful for checking whether the core can read the JSON, whether the port can be opened, and whether an application points to the correct proxy port, but it does not include a remote proxy server. With listen set to 127.0.0.1, other devices on the LAN cannot connect to the port. Before binding to all network interfaces, define the access scope and system firewall rules.

JSON Syntax Boundaries

JSON object keys and strings must use double quotes. Do not leave a trailing comma after the last item in an array or object. Boolean values must be written as true or false, and port numbers must not be quoted. Standard JSON does not support comments, so explanatory text belongs in external documentation or a client notes field, not in the runtime configuration. When copying examples, watch for full-width punctuation, curly quotes and invisible spaces, which rich-text editors often introduce.

Configuration readability mainly comes from indentation, tags and clear sections. Two-space indentation is recommended. Use short English tags that describe their purpose, such as local-socks, proxy, direct and block. Do not rely on array position to convey meaning. Stable tags reduce accidental references when adding outbounds or changing routes. If the goal is simply to import a subscription and connect, there is no need to write the entire file by hand; follow the V2Ray usage guide instead. To choose a client, visit the Download Center.

02 · INBOUNDS

inbounds: Listeners, Protocols and Traffic Entry Points

What an inbound does

inbounds is an array in which each element represents an independent entry point. Desktop clients commonly use local SOCKS and HTTP proxy ports; transparent proxying may also use dokodemo-door. Once a request enters the core, it carries properties such as the inbound tag, destination address, destination port and network type, which are then passed to the routing module. An inbound does not decide whether traffic ultimately uses a proxy, a direct connection or a block; it only accepts, parses and feeds the request into the processing chain.

Common fields include tag, listen, port, protocol, settings, sniffing and streamSettings. The structure of settings depends on the protocol: SOCKS can configure authentication and UDP, HTTP can configure accounts, and dokodemo-door can configure a forwarding destination. Fields from different protocols cannot be mixed; placing SOCKS’s udp field in an HTTP inbound will not produce the expected result.

Local SOCKS and HTTP Entry Points

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

The two inbounds use different ports. Applications that support SOCKS connect to 127.0.0.1:10808; applications that support only HTTP proxies connect to 127.0.0.1:10809. The same address and port cannot be listened to by two processes at once. If the client reports that the port is already in use, check whether another client instance, an old core process or another proxy tool is running before deciding whether to stop it or change the port.

auth: "noauth" is suitable for a local inbound bound only to the loopback address. If the listener is exposed to the LAN, access control should not rely solely on application-layer authentication; restrict sources with the system firewall as well. udp: true means that the SOCKS inbound accepts UDP forwarding requests. It does not mean that every outbound protocol, transport and upstream network can complete UDP communication. If web pages work but voice, games or DNS lookups fail, inspect the inbound, routing, outbound and upstream support separately.

sniffing and Destination Recovery

Some applications resolve a domain to an address first, then submit that address to the proxy port. In that case, the routing module may see only an address, so domain rules cannot match directly. sniffing identifies an HTTP hostname or the server name in a TLS handshake when the connection qualifies, giving the routing module a domain hint. It does not turn every connection into an identifiable domain and should not be treated as a general packet-capture feature.

destOverride specifies the types that may be identified. The example enables http and tls. routeOnly: true means the identified result is used mainly for routing decisions rather than directly replacing the original connection target, reducing compatibility differences caused by target rewriting. If an application breaks after destination identification is enabled, enable it only for the SOCKS inbound first and test by application. Do not change routing, DNS and outbound transport at the same time before the cause is known.

Field Recommended checks Common symptom
listen Prefer binding to the loopback address for local use A binding error prevents applications from connecting or exposes the listener more widely
port Confirm that no other process is using the port The core fails to start and the client reports that no connection was established
protocol Match the proxy type actually supported by the application An HTTP request sent to a SOCKS port fails immediately
udp Check outbound and upstream capabilities together TCP works but UDP traffic fails
tag Match the inboundTag in routing exactly A rule restricted to an inbound never matches

Boundaries of multiple entry points

Multiple entry points are useful for separating application sources. For example, give the browser one inbound and development tools another, then use inboundTag in routing rules to direct them to different outbounds. This is clearer than repeatedly changing global rules. If two inbounds need the same policy, there is no reason to split them merely for completeness. The more entry points you add, the more likely you are to encounter port conflicts, incorrect system proxy targets and missing rules.

Android clients usually receive application traffic through the network interface provided by the system. Per-app proxy and bypass options in the interface participate in generating the runtime configuration. The local-listener approach used in desktop JSON cannot be copied directly to mobile. v2rayNG uses the Xray core, while v2flyNG uses the v2fly core; their interface fields and available core capabilities may differ. Before making manual changes, confirm the current client, core and actual configuration output location, then check the fields against that context.

03 · OUTBOUNDS

outbounds: Servers, Protocols and Transport Layers

The Three Layers of an Outbound

outbounds is also an array. Each outbound generally has three layers of information: the common layer uses tag and protocol to identify its purpose; the protocol layer fills in the server address, port and user parameters under settings; the transport layer defines TCP, WebSocket, gRPC, TLS and related options in streamSettings. Check these three layers separately when troubleshooting; a correct protocol does not automatically mean the entire connection is correct.

The server’s protocol, address, port, user identifier, transport, security layer and server name must be read as one set. Changing only the protocol name, or replacing VMess user parameters with VLESS user parameters, does not convert a configuration. The main value of importing a subscription is that the client receives these related fields as a complete node. When entering them manually, compare every item with the server documentation instead of relying on defaults from an old node.

VLESS over TCP with TLS Example

{
  "outbounds": [
    {
      "tag": "proxy",
      "protocol": "vless",
      "settings": {
        "vnext": [
          {
            "address": "server.example.com",
            "port": 443,
            "users": [
              {
                "id": "11111111-1111-4111-8111-111111111111",
                "encryption": "none"
              }
            ]
          }
        ]
      },
      "streamSettings": {
        "network": "tcp",
        "security": "tls",
        "tlsSettings": {
          "serverName": "server.example.com",
          "allowInsecure": false
        }
      }
    },
    {
      "tag": "direct",
      "protocol": "freedom"
    },
    {
      "tag": "block",
      "protocol": "blackhole"
    }
  ]
}

The domain and user identifier in this example only illustrate the structure. A real connection must use the information supplied by the server. address is the connection target and may be a domain or an address; port is numeric. The id in a VLESS user entry identifies the user, while encryption is normally filled in as required by the server. This is separate from outer TLS: the former is a protocol user parameter, while the latter is the transport security layer. They are not interchangeable.

network: "tcp" specifies TCP as the underlying transport. security: "tls" enables TLS, and tlsSettings.serverName specifies the server name used during the handshake, which should normally match the server certificate and deployment details. Keep allowInsecure: false for normal certificate verification. When a connection fails, do not change it to true first to hide the problem; check the system clock, server name, address resolution, certificate coverage and intermediate network instead.

VMess Object Field Placement

{
  "tag": "proxy-vmess",
  "protocol": "vmess",
  "settings": {
    "vnext": [
      {
        "address": "vmess.example.com",
        "port": 443,
        "users": [
          {
            "id": "22222222-2222-4222-8222-222222222222",
            "security": "auto"
          }
        ]
      }
    ]
  },
  "streamSettings": {
    "network": "ws",
    "security": "tls",
    "tlsSettings": {
      "serverName": "vmess.example.com"
    },
    "wsSettings": {
      "path": "/connection"
    }
  }
}

VMess and VLESS may both use vnext, but the fields inside users differ. The VMess example uses security, while the VLESS example uses encryption. WebSocket transport also requires wsSettings, whose path must match the server. If the server requires specific request headers, place them in the corresponding WebSocket settings. TCP, WebSocket and gRPC each have their own configuration object; do not retain unrelated fields left over from another transport.

direct and block are handling exits

The freedom outbound connects directly to the destination and is commonly tagged direct; blackhole terminates matching traffic and is commonly tagged block. These are not remote nodes, but they are important parts of routing configuration. Routing only selects a tag; without an outbound with that name, processing cannot finish. Explicitly defining proxy, direct and block tags makes the intent visible in the file.

The first outbound in the array has special significance: when no routing rule matches, the core normally uses it as the default exit. Outbound order therefore should not be sorted by name alone. To send unmatched traffic through the proxy by default, put the proxy outbound first; to default to a direct connection, put direct first. A safer approach is to write explicit fallback rules for important cases and recheck the actual path after changing the order.

Layer Representative fields What to verify against
Common layer tagprotocol Local name and protocol type
Protocol layer addressportusers Server or subscription information
Transport layer networksecurity Server transport settings
Transport details tlsSettingswsSettings Deployment information such as server name and path
04 · ROUTING

routing: Match Conditions, Rule Order and Exit Selection

Routing rules are processed in order

routing selects an outbound from connection properties. rules is an ordered array. The core checks rules from top to bottom and uses the exit specified by the first matching rule; later rules do not participate in that connection’s selection. Put specific rules first and broad rules later. A rule covering “all ports” or a large address range at the top can easily mask more precise domain rules below it.

Multiple conditions within one rule generally must all be satisfied. If a rule includes inboundTag, domain and port, the inbound, domain and port must all match; satisfying just one is not enough. To express “domain condition or address condition,” split it into two rules pointing to the same outbound. This is clearer and makes the matching path easier to identify in logs.

{
  "routing": {
    "domainStrategy": "IPIfNonMatch",
    "rules": [
      {
        "type": "field",
        "inboundTag": [
          "local-socks"
        ],
        "domain": [
          "full:internal.example.com"
        ],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "ip": [
          "geoip:private"
        ],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "protocol": [
          "bittorrent"
        ],
        "outboundTag": "block"
      },
      {
        "type": "field",
        "network": "tcp,udp",
        "outboundTag": "proxy"
      }
    ]
  }
}

The first rule handles only requests entering through local-socks whose destination is the specified exact domain. The second sends private address ranges directly, keeping local-device traffic away from the remote server. The third handles traffic by an identifiable protocol. The final rule covers remaining TCP and UDP traffic as an explicit fallback. Every outboundTag must exist in outbounds; if a tag is renamed, update its routing references as well.

domainStrategy determines when to resolve

domainStrategy affects whether the routing module further resolves a domain target into an address. AsIs mainly matches the original domain and does not actively resolve it for address rules; IPIfNonMatch tries domain rules first, then resolves an address and tests address rules if no domain rule matches; IPOnDemand triggers resolution earlier when rule evaluation requires an address. More aggressive strategies make address rules more likely to participate, but DNS behavior then has a more direct effect on routing results.

If the configuration mainly relies on domain categories and does not need destination-address matching, start with AsIs. When using geoip or custom subnets as well, IPIfNonMatch is usually easier to understand: check the domain first, then resolve only if nothing matches. If paths change after this field is adjusted, also check DNS server selection, returned addresses and caching instead of inspecting only the routing array.

Domain Matching Forms

Form Meaning When to use
full:example.com Matches only the exact domain A single fixed host
domain:example.com Matches the domain and its usual subdomain range Organizing rules by site domain
regexp:^.+\.example\.com$ Matches with a regular expression When the structure is too complex for the first two forms
geosite:category-ads-all References domain-category data available to the core When the client and core have the corresponding data ready

Regular expressions are flexible but costly to maintain. Characters such as dots must be escaped according to regex rules, and backslashes must also follow JSON string escaping. When full: or domain: can express the match, prefer the more readable form. Category rules depend on data files supplied with the core; if the same rule behaves differently on different devices, check the data source and update time instead of assuming the categories are identical.

Addresses, Ports, Sources and Network Types

ip can contain a single address, a CIDR range or an address category supported by the core. port can contain a single port, a range or a comma-separated combination such as 53 or 80-443. source and sourcePort restrict rules by source information, network distinguishes TCP from UDP, and inboundTag separates application paths by entry point. Combine these conditions around an actual requirement rather than filling in every field for completeness.

A port match identifies only the destination port; it cannot reliably identify an application or protocol. Web services may use non-standard ports, and other services may use common ones. For stable destination identification, combine domains or addresses with the inbound source where possible. Protocol matching depends on whether the core can identify the traffic; if it cannot, the rule will not match. Keep a clear fallback to prevent unidentified connections from taking an unintended exit.

For complex traffic splitting, start with three rules: direct private addresses, send explicitly selected destinations to a specified exit, and use the default exit for everything else. Once the basic path is stable, add domain categories, ports and source conditions in batches. Importing a large rule set at once makes conflicts difficult to locate. For common traffic-splitting terms, consult the Terminology Manual. If a rule matches but the connection still fails, continue checking the outbound and DNS instead of repeatedly reordering matches.

05 · DNS

dns: Resolution Servers, Domain Groups and Routing

The boundary between core DNS and system DNS

dns defines the servers and matching behavior used when the core performs domain resolution internally. It is not the same as all operating-system DNS settings. An application may resolve a domain at the system layer before sending an address to the proxy, or it may submit a domain through the proxy for the core or remote server to resolve. To determine whether a DNS rule participates, first establish which layer performs the resolution and whether the inbound provides domain information through destination identification.

Routing’s domainStrategy may trigger core resolution, and the server address used by an outbound also needs to be resolved. Some DNS queries may then pass through routing again as ordinary traffic. Misconfiguration can create a circular dependency: the core needs to resolve the proxy server’s domain to connect, while the DNS request is routed to a proxy outbound that has not been established. The solution is to give every required startup target a clear, reachable resolution path and keep the rules simple.

{
  "dns": {
    "hosts": {
      "router.example": "192.168.1.1"
    },
    "servers": [
      {
        "address": "223.5.5.5",
        "domains": [
          "domain:example.cn"
        ],
        "expectIPs": [
          "geoip:cn"
        ]
      },
      {
        "address": "1.1.1.1",
        "domains": [
          "domain:example.com"
        ]
      },
      "localhost"
    ],
    "queryStrategy": "UseIP"
  }
}

hosts provides static mappings and is suitable for fixed local service names or a small number of domains that must be overridden explicitly. It is not a replacement for a large domain list. Static mappings do not automatically follow changes in the real service, so configure only maintainable targets. The example maps router.example to a private address to illustrate the structure; use local network information in a real configuration.

servers lists resolution servers in order. Object entries can include domains so that specific domains prefer that server; string entries can serve as general or fallback servers. localhost means using the local system’s resolution capability. If the client manages DNS, it may rewrite the core configuration as well, so runtime configuration and logs are authoritative.

domains and expectIPs

domains determines which domains prefer the current server and uses syntax similar to routing domain rules. Use full: for an exact host, domain: for an entire domain range, and the corresponding category identifier for category data. A server object without domains is usually a general candidate. When multiple servers match, implementation details and query strategy can still affect the result, so avoid overlapping ranges.

expectIPs filters results according to the expected address type. The example requires the first server group to return addresses in a specified category; if it does not, the core may consider other candidates. This expresses a constraint such as “this domain group should resolve to this kind of address,” but it cannot fix an unreachable upstream, a server timeout or missing category data. For troubleshooting, temporarily remove the restriction, confirm that the basic query succeeds, then restore the result constraint.

queryStrategy and Address Families

Strategy Main behavior Check before using
UseIP Allows queries for available address types Whether the system and outbound can handle the returned addresses
UseIPv4 Prefers IPv4 query results Whether the target provides an IPv4 address
UseIPv6 Prefers IPv6 query results Whether the local network and outbound have IPv6 connectivity

The address-family choice must match actual network capability. Resolving an IPv6 address does not mean the device, router, proxy server and outbound chain can reach it. If some domains take a long time to load or recover after switching networks, first check the returned address type and outbound connectivity. Conversely, forcing IPv4 can make targets that offer only IPv6 impossible to resolve. Choose the strategy based on network facts, not as a universal speed boost.

How DNS Requests Pass Through Routing

When a DNS server is specified by address, the query target can go directly through outbound selection. When it is specified by domain, the DNS server’s own domain must first be resolved. If a group of queries should use the proxy, write a recognizable routing rule for the DNS target that cannot create a loop. The simplest check is to draw two paths: who resolves the business domain, and who resolves the DNS server itself. If either path returns to a connection that has not been established, redesign it.

When a domain rule does not take effect, first check whether the application gives the core a domain or an address. If it provides only an address, inspect the SOCKS request mode, destination identification and routing’s domainStrategy. If DNS returns the right result but the connection uses the wrong target, then check the cache, static mappings and client-generated extra rules. Do not change the resolver, address family and routing order at the same time, or you will not know what actually fixed the problem.

For a deeper look at combining domain groups in mainland China and outside China, remote resolution and address rules, read V2Ray DNS Configuration Explained on the blog. That article focuses on solution design; this chapter focuses on fields and execution boundaries. When client options differ from manually written fields, follow the capabilities of the current core and the configuration it actually generates.

06 · POLICY

policy: Timeouts, User Levels and Statistics

policy does not select an outbound

policy defines connection lifecycles and statistics switches; it does not split traffic by domain or address. Common sections include levels and system. levels uses user levels as keys and sets handshake, idle, half-close and statistics options for users at each level. system controls system-level inbound and outbound statistics. To change the exit for a domain, edit routing rather than looking for routing fields in policy.

A level is not a speed tier or a priority order. A protocol user object can reference a policy group by its level; when no level is set explicitly, the default level is generally used. Multiple levels are useful only when different connection lifecycles are actually needed. A typical client configuration can keep one level, reducing reference complexity between user and policy objects.

{
  "policy": {
    "levels": {
      "0": {
        "handshake": 4,
        "connIdle": 300,
        "uplinkOnly": 2,
        "downlinkOnly": 5,
        "statsUserUplink": false,
        "statsUserDownlink": false
      }
    },
    "system": {
      "statsInboundUplink": false,
      "statsInboundDownlink": false,
      "statsOutboundUplink": false,
      "statsOutboundDownlink": false
    }
  }
}

handshake controls how long the connection-establishment phase may wait. A value that is too small can make high-latency networks or slow handshakes fail prematurely; a value that is too large makes genuinely unreachable connections wait longer. It is not the total webpage load timeout and does not set the application’s own request deadline. When a handshake fails, check the address, port, transport and network reachability before adjusting this value.

connIdle is how long a connection may remain open without data activity. A value that is too short can affect long-lived connections, push messages or intermittent transfers; a value that is too long keeps unused connections consuming resources. The right value depends on the workload, and no single number fits every network. On mobile networks that switch frequently, an old connection may remain in the core while no longer being usable, so also consider the client’s reconnect behavior.

uplinkOnly and downlinkOnly control how long a connection is retained after one direction has half-closed. The other direction may still need a short period to finish sending data. Ending too early can truncate trailing data; retaining it too long delays resource release. For ordinary use, do not adjust these fields first. Test them individually only when logs and application behavior clearly point to half-close handling.

Statistics require two layers to be enabled

statsUserUplink and statsUserDownlink control per-user statistics, while fields under system control inbound and outbound statistics. For statistics to actually be produced, a top-level stats object is usually also required, along with a client or API to read the results. Enabling policy switches alone does not automatically create visible charts or write results to a page.

{
  "stats": {},
  "policy": {
    "system": {
      "statsInboundUplink": true,
      "statsInboundDownlink": true,
      "statsOutboundUplink": true,
      "statsOutboundDownlink": true
    }
  }
}

Statistics add some processing and memory overhead. When observing inbound and outbound traffic temporarily for troubleshooting, enable only what is needed and restore the necessary scope afterward. Per-user statistics also depend on protocol users having the corresponding level and identifier, making them more suitable for server administration or deliberate data collection. A typical local client is more concerned with whether an outbound carries traffic than with creating a statistics layer for every user.

Field Unit or type Adjustment risk
handshake Seconds Too low: the connection-establishment phase ends prematurely
connIdle Seconds Too low affects long-lived connections; too high delays resource release
uplinkOnly Seconds Affects connection retention after uplink ends
downlinkOnly Seconds Affects connection retention after downlink ends
statsInboundUplink Boolean Enabling it produces the related statistics and additional overhead

How to test policy changes

When adjusting connection policies, keep the node, routing and DNS fixed and change only one policy value. Define the test clearly: observe a new connection for handshake issues, establish a connection and wait for idle behavior, and reproduce a one-way shutdown for half-close behavior. Refreshing a webpage once cannot validate every field. Record the original value, new value and observed result after each test so you retain a baseline.

A client may generate a default policy at startup or omit it entirely and use the core defaults. Omitting a field does not mean its value is zero. If the current connection is stable and there is no clear need involving statistics or connection lifecycles, keeping the defaults is usually better than copying parameters from an unknown source. For the platform focus of v2rayN, v2rayNG and v2flyNG, see the side-by-side comparison; field availability still depends on each core and client implementation.

07 · ASSEMBLY

Complete Composition, Loading Checks and Layered Troubleshooting

Combine the sections into a traceable processing chain

A complete configuration is not about the number of fields. Each connection should follow a clear path: the application connects to an inbound, the inbound creates destination information, DNS resolves it when needed, routing selects an outbound, the outbound establishes a connection using its protocol and transport settings, and policy manages the lifecycle. An error at any layer may appear in the client simply as “unable to connect.” Troubleshooting requires breaking that broad symptom into specific stages.

{
  "log": {
    "loglevel": "warning"
  },
  "dns": {
    "servers": [
      "localhost"
    ],
    "queryStrategy": "UseIP"
  },
  "routing": {
    "domainStrategy": "IPIfNonMatch",
    "rules": [
      {
        "type": "field",
        "ip": [
          "geoip:private"
        ],
        "outboundTag": "direct"
      },
      {
        "type": "field",
        "network": "tcp,udp",
        "outboundTag": "proxy"
      }
    ]
  },
  "inbounds": [
    {
      "tag": "local-socks",
      "listen": "127.0.0.1",
      "port": 10808,
      "protocol": "socks",
      "settings": {
        "auth": "noauth",
        "udp": true
      }
    }
  ],
  "outbounds": [
    {
      "tag": "proxy",
      "protocol": "vless",
      "settings": {
        "vnext": [
          {
            "address": "server.example.com",
            "port": 443,
            "users": [
              {
                "id": "11111111-1111-4111-8111-111111111111",
                "encryption": "none"
              }
            ]
          }
        ]
      },
      "streamSettings": {
        "network": "tcp",
        "security": "tls",
        "tlsSettings": {
          "serverName": "server.example.com",
          "allowInsecure": false
        }
      }
    },
    {
      "tag": "direct",
      "protocol": "freedom"
    },
    {
      "tag": "block",
      "protocol": "blackhole"
    }
  ],
  "policy": {
    "levels": {
      "0": {
        "handshake": 4,
        "connIdle": 300
      }
    }
  }
}

This example demonstrates the relationships between sections; replace the server information with actual details. Private addresses match direct first, while remaining TCP and UDP traffic goes to proxy. The SOCKS inbound binds only to the local machine, DNS uses the system resolver, and policy sets only basic connection lifecycles. Although the configuration defines block, no routing rule currently references it; keeping the outbound makes it available for a future explicit blocking rule.

Layer 1: Can the file be read?

First check the file encoding, JSON syntax, key spelling and data types. Common mistakes include a missing comma, a trailing comma, single quotes, a port written as a string, a missing pair of brackets around an array, and full-width punctuation introduced during copying. If the core exits during startup, check the field path and line/column location in the error log first. Do not discuss routing matches until the syntax passes.

Graphical-client users must also confirm that the file is actually loaded by the current process. v2rayN may regenerate the core configuration from the current server, routing and DNS settings; v2rayNG and v2flyNG likewise generate runtime parameters from the mobile interface state. Editing an unused exported file will not change the current connection. Confirm the actual loading path through the client log, configuration preview or startup parameters.

Layer 2: Is the inbound established?

After the core starts, check that the local listening address and port exist. The application’s proxy type must match the inbound protocol: SOCKS must point to a SOCKS port and HTTP to an HTTP port. If the system proxy is enabled but the browser still connects directly, check the system proxy target, the browser’s separate proxy settings and the current client mode. If the application immediately reports that the proxy server refused the connection, first check whether the core is running, the ports match and the local firewall allows the connection.

When only one application fails, do not immediately conclude that the node is broken. The application may ignore the system proxy or have its own DNS, HTTP/3 or network settings. First verify the inbound with a test application that clearly supports SOCKS or HTTP proxies, then inspect proxy support in the target application. On mobile, also check the per-app scope and whether the system network interface has been established.

Layer 3: Do routing and DNS produce the expected target?

After the inbound receives a connection, determine whether the target is a domain or an address, then check the first matching routing rule. If the log shows the wrong outbound, focus on rule order, tag spelling and the combination of conditions. If domain rules do not match but address rules do, inspect where the application resolves the target, along with sniffing and domainStrategy. If resolution times out, temporarily reduce DNS servers and result restrictions to confirm the basic query path.

Routing and DNS problems often affect each other. Ask two separate questions: what does the target domain resolve to, and which rule matches after resolution? Separating these steps reveals whether the result is unexpected or the rule order is wrong. Repeatedly changing nodes will not fix a local rule conflict.

Layer 4: Can the outbound complete the connection?

At the outbound stage, check in a fixed order: server address resolution, port reachability, protocol type, user parameters, transport type, security layer, server name, path or service name. A timeout in the log usually points to reachability or path issues; an immediate disconnect often indicates a port, protocol or handshake-parameter mismatch. An incorrect system clock can also affect TLS. Change one field at a time and keep a restorable copy of the working configuration.

Symptom Check first Next step
The core exits immediately after startup JSON syntax, field types and port usage Read the field path in the error log
The application cannot connect to the local proxy Inbound address, port and protocol type Confirm the application proxy settings and core process
Some domains use the wrong exit Rule order, target type and DNS results Record the first matching rule
All remote connections time out Server resolution, port and network path Then verify the transport and security layer
TCP works but UDP fails Inbound UDP, routing network type and outbound capability Check the upstream and application behavior
Nothing changes after restarting The actually loaded file and client auto-generation Trace the setting back from the runtime configuration

Log levels and minimal reproduction

For everyday use, keep the log level reasonably concise. When locating a problem, temporarily increase the detail, reproduce one clearly defined action, then restore the original setting. More logs do not automatically mean faster conclusions; read them around the timestamp, inbound tag, target, routing result and outbound error. Before sharing logs, remove sensitive information such as server addresses, user identifiers, subscription contents and local paths.

A minimal reproduction configuration keeps one inbound, one proxy outbound, one direct outbound and the fewest possible rules. If it connects, add DNS groups, extra inbounds, complex routing and policy sections one at a time. The step where the problem returns identifies the newly added section. If the minimal configuration also fails, focus on server parameters, network path and core compatibility. This is more reliable than randomly deleting fields from a complete configuration.

If the cause is still unclear, continue by symptom in FAQ Troubleshooting. To reinstall a client or confirm platform compatibility, visit the Download Center and choose v2rayN, v2rayNG or v2flyNG. v2rayN is the first choice for desktop platforms; on Android, choose v2rayNG or v2flyNG according to the core you need. Before reinstalling, record the current subscription, routing and DNS settings so configuration issues are not confused with program issues in the same operation.