xray

package
v1.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 26, 2026 License: AGPL-3.0 Imports: 25 Imported by: 0

Documentation

Overview

Package xray models the Xray-core config as typed Go structs (so field-name mistakes are compile errors) and supervises the Xray child process.

Engine note: Xray-core is the single proxy engine for every lane — the three built-in ones (VLESS-Vision-TCP-443 with a fallback to the panel, VLESS-XHTTP- REALITY on its own port, Hysteria2-UDP with port-hopping) and every operator- defined custom inbound.

Index

Constants

View Source
const (
	TagVLESS    = "vless-in"
	TagHysteria = "hysteria-in"
	TagReality  = "vless-reality-in"
)

Inbound tags (also the keys the live add/remove-user API addresses). A custom inbound's tag is derived from its row id — see model.Inbound.Tag.

View Source
const APIPort = 10085

APIPort is the loopback port for the Xray gRPC StatsService.

View Source
const PinnedVersion = "v26.6.27"

PinnedVersion is the Xray-core release auto-installed when no binary is found. Keep in sync with deploy/install-xray.sh and the Dockerfile ARG.

Why pinned: Xray 26.3.27 shipped a broken Hysteria2 server-side auth handshake (26.6.x fixes it). A floating "latest" can silently regress, so we pin an exact release and its checksums.

View Source
const VisionFlow = "xtls-rprx-vision"

VisionFlow is the VLESS flow used for raw-TCP Vision.

Variables

This section is empty.

Functions

func EnabledInboundTags

func EnabledInboundTags(set *model.Settings, custom []model.Inbound) []string

EnabledInboundTags lists the inbound tags that currently carry users (the targets for live user removal via `xray api rmu`) — built-in lanes plus custom inbounds.

func EnsureBinary

func EnsureBinary(dir string) (string, error)

EnsureBinary returns the path to an Xray binary in dir, downloading the pinned release there if one isn't already present. It lets a fresh box come up without a separate install step when no system Xray (XRAY_BIN / PATH) is found.

func VersionMatchesPinned added in v1.0.0

func VersionMatchesPinned(v string) bool

VersionMatchesPinned reports whether a reported Xray version is the pinned release, tolerating a leading "v": PinnedVersion carries it, but `xray version` output does not (Supervisor.Version parses "26.6.27"), so a plain string compare would spuriously flag every node as version-skewed.

Types

type API

type API struct {
	Tag      string   `json:"tag"`
	Services []string `json:"services"`
}

API exposes gRPC services (StatsService) on the api-tagged inbound.

type Balancer

type Balancer struct {
	Tag         string            `json:"tag"`
	Selector    []string          `json:"selector"`
	Strategy    *BalancerStrategy `json:"strategy,omitempty"`
	FallbackTag string            `json:"fallbackTag,omitempty"`
}

Balancer load-balances across the outbounds whose tag matches a Selector prefix. leastPing + the Observatory route to the fastest live one; FallbackTag is used when none are healthy.

type BalancerStrategy

type BalancerStrategy struct {
	Type string `json:"type"`
}

BalancerStrategy selects the balancing algorithm ("leastPing" | "random" | …).

type Certificate

type Certificate struct {
	CertificateFile string `json:"certificateFile,omitempty"`
	KeyFile         string `json:"keyFile,omitempty"`
}

Certificate points at on-disk PEM files (shared cert for all listeners).

type Config

type Config struct {
	Log         *Log         `json:"log,omitempty"`
	Stats       *Stats       `json:"stats,omitempty"`
	API         *API         `json:"api,omitempty"`
	Policy      *Policy      `json:"policy,omitempty"`
	DNS         *DNS         `json:"dns,omitempty"`
	Inbounds    []Inbound    `json:"inbounds"`
	Outbounds   []Outbound   `json:"outbounds"`
	Routing     *Routing     `json:"routing,omitempty"`
	Observatory *Observatory `json:"observatory,omitempty"`
}

Config is the top-level Xray configuration document.

func Generate

func Generate(set *model.Settings, users []model.User, opts Options, proxies map[string][]model.ProxyEndpoint) (*Config, error)

Generate builds the full Xray config from settings + enabled users.

Layout (all on one box):

  • VLESS-Vision inbound owns :443 + TLS. Its only fallback is the default one → the Go panel (decoy/panel/sub), so :443 has no path that behaves differently from an ordinary website under probing.
  • VLESS-XHTTP-REALITY on its own port, borrowing the donor's TLS.
  • Hysteria2 inbound on :<hysteria_port> (UDP), its own TLS; host nftables redirects the hop range to it.
  • Every operator-defined custom inbound, each on its own port (opts.Custom).
  • One credential set per user (uuid for VLESS, password for Trojan/Hy2).

proxies holds the live upstream proxies of each egress lane, keyed by lane ID.

type DNS

type DNS struct {
	Servers []string `json:"servers,omitempty"`
}

DNS is the Xray DNS block. Servers are upstream resolvers — plain IPs ("1.1.1.1"), DoH URLs ("https://dns.google/dns-query"), or "localhost".

type DokodemoSettings

type DokodemoSettings struct {
	Address string `json:"address"`
}

DokodemoSettings is the settings block for the api inbound.

type Fallback

type Fallback struct {
	Path string `json:"path,omitempty"`
	Dest any    `json:"dest"`
	Xver int    `json:"xver,omitempty"`
}

Fallback routes non-VLESS traffic on the shared port. Dest is an int port or "host:port" string. Used in M2+ to send browser/Trojan traffic to the panel.

type GRPCSettings

type GRPCSettings struct {
	ServiceName string `json:"serviceName"`
	Authority   string `json:"authority,omitempty"`
	MultiMode   bool   `json:"multiMode,omitempty"`
}

GRPCSettings configures the gRPC transport. Authority overrides the :authority pseudo-header; MultiMode multiplexes several streams over one connection.

Note: current Xray marks the gRPC transport itself deprecated in favour of XHTTP stream-up over H2 (it prints a warning on every start). It stays available because existing clients speak it, but new lanes are better off on XHTTP.

type HTTPInboundSettings

type HTTPInboundSettings struct {
	Accounts []ProxyUser `json:"accounts,omitempty"`
}

HTTPInboundSettings is the "settings" object for an http forward-proxy inbound.

type HTTPRequest added in v1.5.0

type HTTPRequest struct {
	Version string              `json:"version,omitempty"`
	Method  string              `json:"method,omitempty"`
	Path    []string            `json:"path,omitempty"`
	Headers map[string][]string `json:"headers,omitempty"`
}

HTTPRequest is the client-to-server half of the raw-TCP HTTP masquerade.

type HTTPResponse added in v1.5.0

type HTTPResponse struct {
	Version string              `json:"version,omitempty"`
	Status  string              `json:"status,omitempty"`
	Reason  string              `json:"reason,omitempty"`
	Headers map[string][]string `json:"headers,omitempty"`
}

HTTPResponse is the server-to-client half.

type HTTPUpgradeSettings added in v1.5.0

type HTTPUpgradeSettings struct {
	Path string `json:"path,omitempty"`
	Host string `json:"host,omitempty"`
	// AcceptProxyProtocol reads the real client IP from a PROXY-protocol header
	// prepended by an upstream that forwards to this inbound.
	AcceptProxyProtocol bool `json:"acceptProxyProtocol,omitempty"`
}

HTTPUpgradeSettings configures the HTTPUpgrade transport — a WebSocket-shaped upgrade without the WebSocket framing, so it fronts the same CDNs but carries no per-frame masking.

type HysteriaClient

type HysteriaClient struct {
	Auth  string `json:"auth"`
	Email string `json:"email,omitempty"`
}

HysteriaClient is one Hysteria2 user. Xray's infra/conf parser maps the JSON "auth" field directly to the Account.Auth protobuf field — using "password" silently gives empty auth.

type HysteriaInboundSettings

type HysteriaInboundSettings struct {
	Version int              `json:"version"` // must be 2
	Users   []HysteriaClient `json:"users"`
}

HysteriaInboundSettings is the "settings" object for a Hysteria2 inbound. Per Xray's schema the per-user list is "users" (NOT "clients" like Trojan/ VLESS) — using the wrong key leaves Xray with no users, so traffic isn't attributed to an email (breaking per-user stats and IP/access logging).

type HysteriaSettings

type HysteriaSettings struct {
	Version int `json:"version"` // must be 2
}

HysteriaSettings is the Hysteria2 transport block. Xray models Hysteria2 as a streamSettings transport (network "hysteria"); per-user auth lives in the inbound's settings.clients[].auth.

type Inbound

type Inbound struct {
	Tag            string          `json:"tag,omitempty"`
	Listen         string          `json:"listen,omitempty"`
	Port           int             `json:"port"`
	Protocol       string          `json:"protocol"`
	Settings       any             `json:"settings,omitempty"`
	StreamSettings *StreamSettings `json:"streamSettings,omitempty"`
	Sniffing       *Sniffing       `json:"sniffing,omitempty"`
}

Inbound is one listening proxy endpoint. Settings is protocol-specific.

func UserInbounds

func UserInbounds(set *model.Settings, custom []model.Inbound, users []model.User, serverID int64, access map[int64]model.Access) []Inbound

UserInbounds builds inbound stubs (tag + protocol + clients) for the given users on every inbound that carries users — the built-in lanes AND each custom inbound. Used by the live add-user API (`xray api adu`) so a new user joins the running Xray without a restart.

Driving this from the actual inbound list, rather than from the settings booleans, is what keeps custom inbounds in step: a user added while one exists reaches it immediately instead of at the next full restart, and — the half that matters more — a user removed is gone from it just as fast. serverID + access gate which inbounds each added user is placed into, exactly as the full generator does — so a live add can never put a user into a lane their groups don't grant.

type LevelPolicy

type LevelPolicy struct {
	StatsUserUplink   bool `json:"statsUserUplink"`
	StatsUserDownlink bool `json:"statsUserDownlink"`
	ConnIdle          int  `json:"connIdle,omitempty"`
	BufferSize        int  `json:"bufferSize,omitempty"`
}

LevelPolicy enables per-user traffic stats for a policy level and bounds a connection's memory: ConnIdle reaps idle connections; BufferSize caps the per-connection buffer (KB) so many concurrent flows can't balloon RSS.

type Log

type Log struct {
	Loglevel string `json:"loglevel,omitempty"`
}

Log configures Xray logging.

type Observatory

type Observatory struct {
	SubjectSelector   []string `json:"subjectSelector"`
	ProbeURL          string   `json:"probeUrl,omitempty"`
	ProbeInterval     string   `json:"probeInterval,omitempty"`
	EnableConcurrency bool     `json:"enableConcurrency,omitempty"`
}

Observatory periodically probes the proxy-pool outbounds (subjectSelector tag prefixes) so the balancer's leastPing strategy can skip dead/slow proxies.

type Options

type Options struct {
	// PanelDest is where the VLESS default fallback forwards non-proxy traffic
	// (the Go panel's loopback HTTP address, e.g. "127.0.0.1:8080").
	PanelDest string

	// Groups resolves the "iplist:<source>/<group>" routing entries to their
	// domains/CIDRs. Parsed from the on-disk iplist databases and cached by the
	// caller (they only change on a geo refresh). Nil or missing groups simply
	// drop those rules — see expandGroups.
	Groups geo.GroupSet

	// Custom are this server's operator-defined inbounds (already filtered to the
	// enabled ones). Each gets its own listener beside the built-in lanes; none of
	// them share :443, so nothing here can disturb the Vision inbound or the decoy.
	Custom []model.Inbound

	// ServerID is the server this config is for (LocalNodeID for the master), used to
	// resolve per-user access to the built-in lanes. Access maps a user id to what
	// they may connect to; a user absent from it is unrestricted (see model.AccessOf).
	// A nil Access means the feature is off and every user reaches every lane — the
	// historical behaviour.
	ServerID int64
	Access   map[int64]model.Access
}

Options carries non-DB generation parameters.

type Outbound

type Outbound struct {
	Tag      string `json:"tag,omitempty"`
	Protocol string `json:"protocol"`
	Settings any    `json:"settings,omitempty"`
}

Outbound is one egress. Settings is protocol-specific (nil for freedom/blackhole).

type Policy

type Policy struct {
	Levels map[string]LevelPolicy `json:"levels,omitempty"`
	System *SystemPolicy          `json:"system,omitempty"`
}

Policy turns on per-user up/down counters.

type ProxyOutboundSettings

type ProxyOutboundSettings struct {
	Servers []ProxyServer `json:"servers"`
}

ProxyOutboundSettings is the "settings" object for a socks/http proxy outbound.

type ProxyServer

type ProxyServer struct {
	Address string      `json:"address"`
	Port    int         `json:"port"`
	Users   []ProxyUser `json:"users,omitempty"`
}

ProxyServer is one upstream proxy (with optional auth).

type ProxyUser

type ProxyUser struct {
	User string `json:"user"`
	Pass string `json:"pass"`
}

ProxyUser is the username/password for an authenticated proxy.

type RealitySettings

type RealitySettings struct {
	Show        bool     `json:"show"`
	Dest        string   `json:"dest"`        // "host:port" of the borrowed site
	Xver        int      `json:"xver"`        // PROXY protocol version (0 = off)
	ServerNames []string `json:"serverNames"` // accepted SNIs (the borrowed site)
	PrivateKey  string   `json:"privateKey"`  // X25519 private (base64 raw-url)
	ShortIds    []string `json:"shortIds"`
	// MaxTimeDiff is the anti-replay window in ms: a client whose handshake clock
	// differs by more than this is rejected, so a probe can't replay a captured
	// REALITY auth later. 0 (omitted) disables the check.
	MaxTimeDiff int `json:"maxTimeDiff,omitempty"`
}

RealitySettings configures the REALITY security layer. Instead of presenting our own cert, the inbound forwards the TLS handshake of a real site (Dest / ServerNames) and authenticates clients via the X25519 key + shortId.

type RouteRule

type RouteRule struct {
	Type        string   `json:"type"` // always "field"
	InboundTag  []string `json:"inboundTag,omitempty"`
	Domain      []string `json:"domain,omitempty"`
	IP          []string `json:"ip,omitempty"`
	Port        string   `json:"port,omitempty"`
	Network     string   `json:"network,omitempty"` // "tcp,udp" — catch-all matcher
	Protocol    []string `json:"protocol,omitempty"`
	OutboundTag string   `json:"outboundTag,omitempty"`
	BalancerTag string   `json:"balancerTag,omitempty"`
}

RouteRule is one Xray field rule. Same-field values are OR'd; different fields are AND'd. Traffic goes to OutboundTag, or BalancerTag (a proxy pool).

type Routing

type Routing struct {
	DomainStrategy string      `json:"domainStrategy,omitempty"`
	Rules          []RouteRule `json:"rules,omitempty"`
	Balancers      []Balancer  `json:"balancers,omitempty"`
}

Routing holds the ordered field rules. Unmatched traffic uses the first outbound (direct). Balancers group several outbounds into one egress.

type Sniffing

type Sniffing struct {
	Enabled      bool     `json:"enabled"`
	DestOverride []string `json:"destOverride,omitempty"`
}

Sniffing inspects proxied connections to recover their real destination (HTTP host / TLS SNI / QUIC) so domain routing rules can match it.

type SocksInboundSettings

type SocksInboundSettings struct {
	Auth     string      `json:"auth"`
	Accounts []ProxyUser `json:"accounts,omitempty"`
	UDP      bool        `json:"udp"`
}

SocksInboundSettings is the "settings" object for a socks forward-proxy inbound (proxy mode). Auth is "password" when accounts are present, else "noauth".

type Stats

type Stats struct{}

Stats enables the stats engine (marshals to {}).

type StreamSettings

type StreamSettings struct {
	// Network is the transport: "tcp" | "ws" | "xhttp" | "grpc" | "httpupgrade" |
	// "hysteria".
	Network             string               `json:"network,omitempty"`
	Security            string               `json:"security,omitempty"` // "tls" | "reality" | "" (none)
	TLSSettings         *TLSSettings         `json:"tlsSettings,omitempty"`
	TCPSettings         *TCPSettings         `json:"tcpSettings,omitempty"`
	WSSettings          *WSSettings          `json:"wsSettings,omitempty"`
	XHTTPSettings       *XHTTPSettings       `json:"xhttpSettings,omitempty"`
	HTTPUpgradeSettings *HTTPUpgradeSettings `json:"httpupgradeSettings,omitempty"`
	HysteriaSettings    *HysteriaSettings    `json:"hysteriaSettings,omitempty"`
	RealitySettings     *RealitySettings     `json:"realitySettings,omitempty"`
	GRPCSettings        *GRPCSettings        `json:"grpcSettings,omitempty"`
	// Sockopt is the operator's socket-option block, passed through verbatim. Raw
	// rather than typed: the field set is long, entirely server-local, and validated
	// against a key whitelist before it gets here (model.SockoptKeys), so a typed
	// mirror would be twenty fields of pure transcription with nothing to check.
	Sockopt json.RawMessage `json:"sockopt,omitempty"`
}

StreamSettings configures transport + transport-level security.

type Supervisor

type Supervisor struct {
	// contains filtered or unexported fields
}

Supervisor owns the Xray child process and the on-disk config.json. It serializes config applies: marshal -> validate -> atomic swap -> restart, and supervises the process — an unexpected exit is auto-restarted with backoff.

If no Xray binary is available (e.g. local dev on macOS), Apply still writes and the panel keeps running; it just logs that Xray isn't being (re)started.

func NewSupervisor

func NewSupervisor(binName, configPath, assetDir string) *Supervisor

NewSupervisor resolves binName (via PATH or as an absolute path) and targets configPath for the generated config. assetDir holds the geo databases.

func (*Supervisor) APIAddr

func (s *Supervisor) APIAddr() string

APIAddr is the loopback address of Xray's gRPC API (StatsService + live user add/remove). The wiring lives here so callers don't rebuild it ad hoc.

func (*Supervisor) AddUsers

func (s *Supervisor) AddUsers(apiAddr string, inbounds []Inbound) error

func (*Supervisor) Apply

func (s *Supervisor) Apply(cfg *Config) error

Apply writes the config atomically (validating first when possible) and restarts Xray.

func (*Supervisor) ApplyRaw added in v1.0.0

func (s *Supervisor) ApplyRaw(data []byte) error

ApplyRaw is Apply for a config that is already marshaled JSON — used by the node agent, which receives the exact config the panel generated and applies it verbatim (after substituting its own cert paths) rather than round-tripping it through the Config struct. Same validate → atomic swap → restart, with the same rollback backup, so a config the node's Xray can't parse never kills it.

func (*Supervisor) AssetDir

func (s *Supervisor) AssetDir() string

AssetDir returns the directory holding the geoip.dat / geosite.dat databases.

func (*Supervisor) BinPath added in v0.15.0

func (s *Supervisor) BinPath() string

BinPath returns the resolved Xray binary, or "" if none was found. The self-test spawns a throwaway Xray client from the same binary, so it needs this.

func (*Supervisor) ConfigBytes

func (s *Supervisor) ConfigBytes() ([]byte, error)

ConfigBytes returns the on-disk config.json currently applied to Xray.

func (*Supervisor) HasBackup

func (s *Supervisor) HasBackup() bool

HasBackup reports whether a rollback config (config.json.bak) is available.

func (*Supervisor) LogTail

func (s *Supervisor) LogTail() []string

LogTail returns the buffered recent Xray log lines.

func (*Supervisor) QueryStats

func (s *Supervisor) QueryStats(apiAddr string) (map[string]Traffic, error)

QueryStats reads per-user traffic counters from the running Xray StatsService (via `xray api statsquery`). Keyed by user email (we use "u<id>").

func (*Supervisor) RemoveUsers

func (s *Supervisor) RemoveUsers(apiAddr string, tags, emails []string) error

RemoveUsers removes users (by email) from each given inbound tag via `xray api rmu` (no restart).

func (*Supervisor) Restart added in v0.13.0

func (s *Supervisor) Restart() error

Restart stops the running Xray and starts a fresh one from the config already on disk. Unlike Apply it neither regenerates nor re-validates the config — it is the operator's "kick it" button for a wedged or misbehaving process, and it also makes a process-level change (e.g. the TZ the child runs in) take effect without waiting for the next config change.

Every live VPN connection is dropped, so this is only ever operator-initiated.

func (*Supervisor) Resume added in v1.4.0

func (s *Supervisor) Resume() error

Resume lifts a Suspend and starts Xray from the config on disk.

Lifting the suspension is deliberately NOT a side effect of Apply or Restart. A suspended node is one the panel switched off, and it still does everything else — renews its certificate, accepts a config, keeps checking in — so any of those paths would quietly put it back to serving users. Coming back has to be something the caller asks for by name, in the one place that knows the panel switched it on again.

func (*Supervisor) Running

func (s *Supervisor) Running() bool

Running reports whether the Xray child process is currently up. Reflects reality: a crashed process clears s.cur until a restart succeeds. Callers that drive logic (health decisions, auto-restart) want this exact instantaneous truth.

func (*Supervisor) Serving added in v1.4.0

func (s *Supervisor) Serving() bool

Serving reports whether Xray is up OR in the middle of a deliberate restart — the answer to "is this server working", not "is a process alive this instant".

It exists for status REPORTING, where Running() lies by omission. A restart (operator button, cert renewal, config push) holds the process down for about a second; a node's sync landing in that window would report xray_running=false and paint the server as down for a full poll cycle, for what is really a healthy bounce. A crash is different — that clears s.cur without setting restarting, so Serving is false for it, which is correct: a crash IS an outage.

func (*Supervisor) SetOnAccess

func (s *Supervisor) SetOnAccess(fn func(email, ip, dest string))

SetOnAccess registers a callback invoked for each Xray access-log line that carries a user email + source IP (used to track online status / connections). dest is the destination host when the line has a usable one, else empty.

func (*Supervisor) SetOnCrash added in v0.7.0

func (s *Supervisor) SetOnCrash(fn func(err error))

SetOnCrash registers a callback invoked when the Xray child exits unexpectedly (a genuine crash, not an intentional Stop/Apply). Used to alert the operator.

func (*Supervisor) SetOnRecover added in v1.2.0

func (s *Supervisor) SetOnRecover(fn func())

SetOnRecover registers a callback invoked when Xray comes back after a crash.

func (*Supervisor) StartedAt

func (s *Supervisor) StartedAt() int64

StartedAt returns the unix start time of the current Xray process, or 0 if it's down. It changes on every (re)start, so clients can detect a config reload.

func (*Supervisor) Stop

func (s *Supervisor) Stop()

Stop terminates the Xray process and permanently closes the supervisor: every later Apply/Restart is silently ignored. It is for process shutdown only — use Suspend for a stop you intend to come back from.

func (*Supervisor) SubscribeLogs

func (s *Supervisor) SubscribeLogs() (<-chan string, func())

SubscribeLogs returns a channel of new Xray log lines and an unsubscribe func.

func (*Supervisor) Suspend added in v1.4.0

func (s *Supervisor) Suspend()

Suspend terminates the Xray process but leaves the supervisor usable, so a later Apply or Restart brings it back. The auto-restart never fires for it: stopProc marks the process as killed on purpose, which is what the monitor keys on — the closed latch is not needed for that and is exactly what makes Stop one-way.

This exists because a node stops serving for two very different reasons. One is the agent going away; the other is the panel revoking it (disabled or deleted), which is reversible — re-enable it and it must serve again. Using Stop for the second poisoned the supervisor for good: the node kept syncing, applied every config it was pushed, reported each operator restart as a success, and never ran Xray again until its process was restarted by hand.

func (*Supervisor) UptimeSeconds

func (s *Supervisor) UptimeSeconds() int64

UptimeSeconds reports how long the current Xray process has been running, or 0 if it's down.

func (*Supervisor) ValidateBytes added in v1.5.0

func (s *Supervisor) ValidateBytes(data []byte) error

ValidateBytes runs `xray run -test` over a config WITHOUT applying it, and returns Xray's own complaint when it refuses.

This is what lets the panel reject a bad advanced setting in the editor instead of storing it, pushing it, and finding out from a crashed Xray and a rollback. Nothing but Xray can answer the question — the settings it accepts are defined by its parser, and a panel-side whitelist only catches misspelled keys, not values it dislikes.

A missing binary means "cannot judge", not "invalid": the caller then falls back to its own checks rather than blocking every save.

func (*Supervisor) ValidateConfig added in v1.5.0

func (s *Supervisor) ValidateConfig(cfg *Config) error

ValidateConfig is ValidateBytes for a config still in struct form.

func (*Supervisor) Version

func (s *Supervisor) Version() string

Version returns the Xray version string (e.g. "26.6.1"), cached after the first call. Empty when no binary is available.

func (*Supervisor) WriteConfig

func (s *Supervisor) WriteConfig(cfg *Config) error

WriteConfig atomically writes config.json WITHOUT validating or restarting Xray. Used after live user add/remove so a crash-restart (the monitor reloads from disk) preserves the change. The content is generated by trusted code, so validation (which would reparse the geo DBs and cost seconds) is skipped.

type SystemPolicy

type SystemPolicy struct {
	StatsInboundUplink    bool `json:"statsInboundUplink"`
	StatsInboundDownlink  bool `json:"statsInboundDownlink"`
	StatsOutboundUplink   bool `json:"statsOutboundUplink"`
	StatsOutboundDownlink bool `json:"statsOutboundDownlink"`
}

SystemPolicy enables system-wide traffic stats.

type TCPHeader added in v1.5.0

type TCPHeader struct {
	Type     string        `json:"type"`
	Request  *HTTPRequest  `json:"request,omitempty"`
	Response *HTTPResponse `json:"response,omitempty"`
}

TCPHeader is the raw-TCP masquerade. Type is "none" or "http"; for "http" the request/response templates decide what the framing claims to be.

type TCPSettings added in v1.5.0

type TCPSettings struct {
	Header *TCPHeader `json:"header,omitempty"`
}

TCPSettings configures the raw-TCP transport. Header carries the optional HTTP masquerade — the framing that makes a raw proxy stream open like an ordinary HTTP exchange. Left nil the transport sends proxy bytes straight away.

type TLSSettings

type TLSSettings struct {
	ServerName       string        `json:"serverName,omitempty"`
	RejectUnknownSni bool          `json:"rejectUnknownSni,omitempty"`
	ALPN             []string      `json:"alpn,omitempty"`
	MinVersion       string        `json:"minVersion,omitempty"`
	Certificates     []Certificate `json:"certificates,omitempty"`

	// Extra are additional tlsSettings keys the operator supplied. Merged at
	// marshal time (see MarshalJSON) rather than stored as a sibling block, because
	// Xray reads one flat tlsSettings object — there is nowhere for a second one to
	// go. Validated against model.TLSExtraKeys before it reaches here, so it cannot
	// contain the fields above that the panel owns.
	Extra json.RawMessage `json:"-"`
}

TLSSettings configures the TLS layer for an inbound.

func (TLSSettings) MarshalJSON added in v1.5.0

func (t TLSSettings) MarshalJSON() ([]byte, error)

MarshalJSON emits the derived fields with the operator's extra keys folded in.

Written by hand because the alternative is making the whole block a raw blob, which would cost every other call site its compile-time field checking — the reason these structs are typed at all. The alias type breaks the recursion.

type Traffic

type Traffic struct {
	Up   int64
	Down int64
}

Traffic is a per-user uplink/downlink counter snapshot.

type TrojanClient

type TrojanClient struct {
	Password string `json:"password"`
	Email    string `json:"email,omitempty"`
}

TrojanClient is one Trojan user.

type TrojanInboundSettings

type TrojanInboundSettings struct {
	Clients []TrojanClient `json:"clients"`
}

TrojanInboundSettings is the "settings" object for a Trojan inbound.

type VLESSClient

type VLESSClient struct {
	ID    string `json:"id"`             // UUID
	Flow  string `json:"flow,omitempty"` // "xtls-rprx-vision"
	Email string `json:"email,omitempty"`
}

VLESSClient is one VLESS user.

type VLESSInboundSettings

type VLESSInboundSettings struct {
	Clients    []VLESSClient `json:"clients"`
	Decryption string        `json:"decryption"` // always "none" for VLESS
	Fallbacks  []Fallback    `json:"fallbacks,omitempty"`
}

VLESSInboundSettings is the "settings" object for a VLESS inbound.

type WSSettings

type WSSettings struct {
	Path string `json:"path,omitempty"`
	Host string `json:"host,omitempty"`
	// AcceptProxyProtocol reads the real client IP from a PROXY-protocol header
	// prepended by an upstream that forwards to this inbound.
	AcceptProxyProtocol bool `json:"acceptProxyProtocol,omitempty"`
}

WSSettings configures the WebSocket transport.

type WireGuardPeer

type WireGuardPeer struct {
	PublicKey  string   `json:"publicKey"`
	Endpoint   string   `json:"endpoint"`
	AllowedIPs []string `json:"allowedIPs,omitempty"`
}

WireGuardPeer is one WireGuard peer (Cloudflare's WARP endpoint).

type WireGuardSettings

type WireGuardSettings struct {
	SecretKey string          `json:"secretKey"`
	Address   []string        `json:"address"`
	Peers     []WireGuardPeer `json:"peers"`
	Reserved  []int           `json:"reserved,omitempty"`
	MTU       int             `json:"mtu,omitempty"`
}

WireGuardSettings is the "settings" object for a wireguard outbound (used for the Cloudflare WARP egress).

type XHTTPSettings added in v1.5.0

type XHTTPSettings struct {
	Path  string          `json:"path,omitempty"`
	Host  string          `json:"host,omitempty"`
	Mode  string          `json:"mode,omitempty"`
	Extra json.RawMessage `json:"extra,omitempty"`
}

XHTTPSettings configures the XHTTP transport (Xray's HTTP-shaped transport, the successor to SplitHTTP). Mode is "" (Xray's default), "packet-up", "stream-up" or "stream-one"; with REALITY the default resolves to stream-one — one HTTP request per connection, which is both the smallest surface and the only shape that would survive path-based dispatch.

Host is the Host header the client sends; empty means the client uses the address it dialled, which is what we want when the inbound isn't behind a CDN.

Extra is the operator's advanced block, passed through verbatim. Xray reads `extra` as a COMPLETE XHTTP config and then overwrites its host/path/mode from the outer three, which is what lets the same object be handed to the client in the share link's extra= parameter with no translation.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL