VXVX Docs

Router

RouterConfig and RuleConfig

Routing is configured in ServerConfig.router (RouterConfig).

Schema definition: protos/proto/vx/router/router.proto.

Rules are evaluated in order; the first matching rule determines the outbound or selector. Subsequent rules are not considered after a match.

Examples

Route everything to direct:

{
  "router": {
    "rules": [
      { "matchAll": true, "outboundTag": "direct" }
    ]
  }
}

Route a specific inbound to a specific outbound:

{
  "router": {
    "rules": [
      {
        "inboundTags": ["trojan"],
        "matchAll": true,
        "outboundTag": "direct"
      }
    ]
  }
}

RouterConfig

rules

Ordered routing rules

RuleConfig

Target: Exactly one of outboundTag and selectorTag must be set. If both are empty, the connection will be blocked.

outboundTag
string

Send to this outbound handler

selectorTag
string

Send to a selector (client / load balancing)

condition

Metadata used to match connections

fallbacks

Try alternate selectors/outbounds when the primary target fails

ruleName
string

Name

Fallback

selectorTag
string

Fallback selector (mutually exclusive with outboundTag)

outboundTag
string

Fallback outbound (mutually exclusive with selectorTag)

action

Additional action on fallback

condition

Condition for this fallback; the fallback applies only when it matches

last
bool

If the condition matches, this fallback is final and later fallbacks are not considered

Action

Fields for Fallback.action:

ipToDomain
bool

Rewrite the IP back to a domain on fallback

Condition

Used in rule.condition or fallback.condition.

matchAll
bool

Match all connections

usernames
string[]

Match authenticated user IDs

srcCidrs
string[]

Source IP match

srcIpTags
string[]

Source IP match using set names from Geo

dstCidrs
string[]

Destination IP match

dstIpTags
string[]

Destination IP match using set names from Geo

resolveDomain
bool

Resolve the domain; all IPs must be in dstIpTags or dstCidrs

resolveSoftRewrite
bool

Resolve the domain; any IP in dstIpTags or dstCidrs matches, and rewrite the destination to that IP

resolveSoftNoRewrite
bool

Resolve the domain; any IP in dstIpTags or dstCidrs matches, but do not rewrite the destination

geoDomains

Inline Domain entries for domain matching

domainTags
string[]

Domain match (references geo sets)

networks
Network[]

TCP, UDP, etc.

srcPortRanges

Source port ranges

dstPortRanges

Destination port ranges

appIds

Application ID match

appTags
string[]

Application set match (references geo sets)

protocols
string[]

Protocol sniffing results

ipv6
bool

Match IPv6 only

fakeIp
bool

Match Fake IP destinations

skipSniff
bool

Disable sniffing for connections to IP destinations

inboundTags
string[]

Match inbound tag

SelectorConfig

Selectors filter candidate nodes from a group of outbounds, then pick the node actually used for the connection according to a strategy. Defined in ClientConfig.selectors (SelectorsConfig); primarily used by the VX client. Router rules reference them via selectorTag.

For client UI behavior, see Selectors.

tag
string

Selector name. Referenced by RuleConfig.selectorTag and Fallback.selectorTag.

filter

Filter for the candidate outbound pool; see Filter.

strategy
SelectingStrategy

Which nodes to actually use from the filtered pool:

  • ALL: All nodes in the pool
  • ALL_OK: All available nodes (falls back to untested nodes if none are available)
  • LEAST_PING: Single node with lowest ping
  • MOST_THROUGHPUT: Single node with highest speed-test throughput
  • TOP_PING: All nodes within 30% of the lowest ping (e.g. lowest 100 ms → includes ≤ 130 ms)
  • TOP_THROUGHPUT: All nodes with throughput ≥ 70% of the highest (e.g. highest 100 → includes ≥ 70)

Single-node strategies (LEAST_PING, MOST_THROUGHPUT) do not use balanceStrategy; multi-node strategies require load balancing.

balanceStrategy
BalanceStrategy

For multi-node strategies, which node handles each connection:

  • RANDOM (default): Random choice from the active set; IPv6 connections prefer nodes that support IPv6
  • MEMORY: Sticky reuse of the same node per app or root domain; assigns randomly on first use and remembers the mapping
selectFromOm
bool

On the server, this should be true

speedTestSize
uint32

Download bytes per speed test. When speedTestSizeRange is not set and this is 0, the core defaults to 1 MiB.

speedTestInterval
uint32

Interval for speed-testing filtered nodes (minutes). Only MOST_THROUGHPUT and TOP_THROUGHPUT run periodic speed tests.

pingTestInterval
uint32

Interval for pinging filtered nodes (minutes). Only LEAST_PING and TOP_PING run periodic pings.

unusableTestInterval
uint32

Interval for re-checking nodes marked unusable (minutes). All strategies except ALL check availability.

speedTestSizeRange

Random range for speed-test download size (bytes). When 0 < min ≤ max, each test picks a random value in [min, max]; otherwise speedTestSize is used.

Filter

prefixes
string[]

Outbound tag matches if it starts with any prefix

tags
string[]

Outbound tag matches if it equals any value in the list

subStrings
string[]

Outbound tag matches if it contains any substring (database mode only)

inverse
bool

When true, invert: only outbounds that do not match prefixes / tags are included (outbound manager mode)

SpeedTestSizeRange

min
uint32

Lower bound for random speed-test size (bytes)

max
uint32

Upper bound for random speed-test size (bytes)

  • GeodomainTags, dstIpTags, geoDomains
  • DNS — Resolution for resolveDomain rules
  • Dispatcher — Sniffing affects protocol/domain matching

Comments