Skip to content

Protocol Overview

Xray-core implements a diverse set of proxy protocols, each registered via common.RegisterConfig() in its init() function. The core dispatches inbound connections to the appropriate protocol handler based on configuration, and outbound handlers connect to upstream servers or destinations.

Protocol Capability Matrix

ProtocolInboundOutboundTCPUDPEncryptionMux SupportAuth
VMessYesYesYesYesAES-128-GCM, ChaCha20-Poly1305, NoneYes (v1.mux.cool)UUID + AEAD header
VLESSYesYesYesYesNone (relies on transport TLS)Yes (XUDP)UUID
TrojanYesYesYesYesNone (relies on TLS)NoSHA224(password)
ShadowsocksYesYesYesYesAES-128-GCM, AES-256-GCM, ChaCha20-Poly1305, XChaCha20, NoneNoPer-key
Shadowsocks 2022YesYesYesYes2022-blake3-aes-128-gcm, 2022-blake3-aes-256-gcm, etc.NoPSK (base64)
SOCKS5YesYesYesYes (UDP Associate)NoneNoUsername/Password
HTTPYesYesYesNoNone (HTTPS via transport)NoBasic Auth
Dokodemo-doorYesNoYesYesN/A (transparent)NoN/A
FreedomNoYesYesYesN/A (direct)NoN/A
BlackholeNoYesN/AN/AN/ANoN/A
WireGuardYesYesYesYesNoise protocol (Curve25519, ChaCha20-Poly1305)NoPublic/Private key
Hysteria2YesYesYesYes (QUIC datagram)QUIC TLS 1.3NoPassword-based

Architecture

Inbound Handler Interface

Every inbound protocol implements proxy.Inbound:

go
type Inbound interface {
    Network() []net.Network        // Supported networks (TCP, UDP, UNIX)
    Process(ctx context.Context,
        network net.Network,
        conn stat.Connection,
        dispatcher routing.Dispatcher) error
}

Key source: proxy/proxy.go

Outbound Handler Interface

Every outbound protocol implements proxy.Outbound:

go
type Outbound interface {
    Process(ctx context.Context,
        link *transport.Link,
        dialer internet.Dialer) error
}

Key source: proxy/proxy.go

Registration Pattern

All protocols self-register using the same pattern in their init():

go
func init() {
    common.Must(common.RegisterConfig((*Config)(nil),
        func(ctx context.Context, config interface{}) (interface{}, error) {
            return New(ctx, config.(*Config))
        }))
}

Connection Flow

mermaid
graph LR
    A[Client] -->|Transport Layer| B[Inbound Handler]
    B -->|Decode Protocol| C[Dispatcher]
    C -->|Routing Rules| D[Outbound Handler]
    D -->|Encode Protocol| E[Transport Layer]
    E --> F[Destination]

Splice Copy Levels

The CanSpliceCopy field on inbound/outbound metadata controls zero-copy optimization:

ValueMeaning
0No splice
1Splice allowed (direct/dokodemo)
2Splice possible after handshake (socks/http raw)
3Full splice support (encrypted protocols)

Address Parsing

Most protocols use protocol.NewAddressParser with SOCKS5-style address family bytes:

ByteFamily
0x01IPv4 (4 bytes)
0x03Domain (1-byte length prefix + string)
0x04IPv6 (16 bytes)

VMess uses a different ordering: 0x01 = IPv4, 0x02 = Domain, 0x03 = IPv6, with port-then-address format.

Source: proxy/vmess/encoding/encoding.go:12-17, proxy/trojan/protocol.go:16-20, proxy/shadowsocks/protocol.go:24-31

Key Source Files

ProtocolDirectory
VMessproxy/vmess/ (aead/, encoding/, inbound/, outbound/)
VLESSproxy/vless/
Trojanproxy/trojan/
Shadowsocksproxy/shadowsocks/
Shadowsocks 2022proxy/shadowsocks_2022/
SOCKSproxy/socks/
HTTPproxy/http/
Dokodemo-doorproxy/dokodemo/
Freedomproxy/freedom/
Blackholeproxy/blackhole/
WireGuardproxy/wireguard/
Hysteria2proxy/hysteria/

Technical analysis for re-implementation purposes.