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.