Skip to content

Обзор протоколов

Xray-core реализует разнообразный набор прокси-протоколов, каждый из которых регистрируется через common.RegisterConfig() в своей функции init(). Ядро направляет входящие соединения к соответствующему обработчику протокола на основе конфигурации, а исходящие обработчики подключаются к вышестоящим серверам или конечным точкам назначения.

Матрица возможностей протоколов

ПротоколВходящийИсходящийTCPUDPШифрованиеПоддержка MuxАутентификация
VMessДаДаДаДаAES-128-GCM, ChaCha20-Poly1305, NoneДа (v1.mux.cool)UUID + AEAD-заголовок
VLESSДаДаДаДаНет (зависит от TLS транспортного уровня)Да (XUDP)UUID
TrojanДаДаДаДаНет (зависит от TLS)НетSHA224(пароль)
ShadowsocksДаДаДаДаAES-128-GCM, AES-256-GCM, ChaCha20-Poly1305, XChaCha20, NoneНетПо ключу
Shadowsocks 2022ДаДаДаДа2022-blake3-aes-128-gcm, 2022-blake3-aes-256-gcm и др.НетPSK (base64)
SOCKS5ДаДаДаДа (UDP Associate)НетНетИмя пользователя/Пароль
HTTPДаДаДаНетНет (HTTPS через транспорт)НетBasic Auth
Dokodemo-doorДаНетДаДаН/Д (прозрачный)НетН/Д
FreedomНетДаДаДаН/Д (прямой)НетН/Д
BlackholeНетДаН/ДН/ДН/ДНетН/Д
WireGuardДаДаДаДаПротокол Noise (Curve25519, ChaCha20-Poly1305)НетПубличный/Приватный ключ
Hysteria2ДаДаДаДа (QUIC datagram)QUIC TLS 1.3НетНа основе пароля

Архитектура

Интерфейс входящего обработчика

Каждый входящий протокол реализует 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
}

Ключевой исходный файл: proxy/proxy.go

Интерфейс исходящего обработчика

Каждый исходящий протокол реализует proxy.Outbound:

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

Ключевой исходный файл: proxy/proxy.go

Паттерн регистрации

Все протоколы самостоятельно регистрируются с использованием одного и того же паттерна в своей функции init():

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

Поток соединения

mermaid
graph LR
    A[Клиент] -->|Транспортный уровень| B[Входящий обработчик]
    B -->|Декодирование протокола| C[Диспетчер]
    C -->|Правила маршрутизации| D[Исходящий обработчик]
    D -->|Кодирование протокола| E[Транспортный уровень]
    E --> F[Назначение]

Уровни Splice Copy

Поле CanSpliceCopy в метаданных входящих/исходящих обработчиков управляет оптимизацией нулевого копирования:

ЗначениеОписание
0Без splice
1Splice разрешён (direct/dokodemo)
2Splice возможен после рукопожатия (socks/http raw)
3Полная поддержка splice (зашифрованные протоколы)

Разбор адресов

Большинство протоколов используют protocol.NewAddressParser с байтами семейства адресов в стиле SOCKS5:

БайтСемейство
0x01IPv4 (4 байта)
0x03Домен (1 байт длины + строка)
0x04IPv6 (16 байт)

VMess использует другой порядок: 0x01 = IPv4, 0x02 = Домен, 0x03 = IPv6, с форматом порт-затем-адрес.

Исходный код: proxy/vmess/encoding/encoding.go:12-17, proxy/trojan/protocol.go:16-20, proxy/shadowsocks/protocol.go:24-31

Ключевые исходные файлы

ПротоколКаталог
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/

Технический анализ для целей повторной реализации.