package vless import ( "encoding/binary" "fmt" "io" "net" ) const ( Version = 0 CmdTCP byte = 0x01 CmdUDP byte = 0x02 AddrIPv4 byte = 0x01 AddrDomain byte = 0x02 AddrIPv6 byte = 0x03 ) // Request represents a parsed VLESS request header. type Request struct { UUID [16]byte Command byte Port uint16 Address string Addons []byte } // Target returns the address:port string for dialing. func (r *Request) Target() string { return net.JoinHostPort(r.Address, fmt.Sprintf("%d", r.Port)) } // ParseRequest reads a VLESS request header from r. func ParseRequest(r io.Reader) (*Request, error) { // Version (1 byte). var ver [1]byte if _, err := io.ReadFull(r, ver[:]); err != nil { return nil, fmt.Errorf("reading version: %w", err) } if ver[0] != Version { return nil, fmt.Errorf("unsupported VLESS version: %d", ver[0]) } // UUID (16 bytes). var req Request if _, err := io.ReadFull(r, req.UUID[:]); err != nil { return nil, fmt.Errorf("reading UUID: %w", err) } // Addons length (1 byte) + addons. var addonsLen [1]byte if _, err := io.ReadFull(r, addonsLen[:]); err != nil { return nil, fmt.Errorf("reading addons length: %w", err) } if addonsLen[0] > 0 { req.Addons = make([]byte, addonsLen[0]) if _, err := io.ReadFull(r, req.Addons); err != nil { return nil, fmt.Errorf("reading addons: %w", err) } } // Command (1 byte). var cmd [1]byte if _, err := io.ReadFull(r, cmd[:]); err != nil { return nil, fmt.Errorf("reading command: %w", err) } req.Command = cmd[0] if req.Command != CmdTCP && req.Command != CmdUDP { return nil, fmt.Errorf("unsupported command: 0x%02x", req.Command) } // Port (2 bytes, big-endian). var portBuf [2]byte if _, err := io.ReadFull(r, portBuf[:]); err != nil { return nil, fmt.Errorf("reading port: %w", err) } req.Port = binary.BigEndian.Uint16(portBuf[:]) // Address type (1 byte) + address. var addrType [1]byte if _, err := io.ReadFull(r, addrType[:]); err != nil { return nil, fmt.Errorf("reading address type: %w", err) } switch addrType[0] { case AddrIPv4: var ip [4]byte if _, err := io.ReadFull(r, ip[:]); err != nil { return nil, fmt.Errorf("reading IPv4 address: %w", err) } req.Address = net.IP(ip[:]).String() case AddrDomain: var domainLen [1]byte if _, err := io.ReadFull(r, domainLen[:]); err != nil { return nil, fmt.Errorf("reading domain length: %w", err) } domain := make([]byte, domainLen[0]) if _, err := io.ReadFull(r, domain); err != nil { return nil, fmt.Errorf("reading domain: %w", err) } req.Address = string(domain) case AddrIPv6: var ip [16]byte if _, err := io.ReadFull(r, ip[:]); err != nil { return nil, fmt.Errorf("reading IPv6 address: %w", err) } req.Address = net.IP(ip[:]).String() default: return nil, fmt.Errorf("unsupported address type: 0x%02x", addrType[0]) } return &req, nil } // WriteResponse writes the VLESS response header (version 0, no addons). func WriteResponse(w io.Writer) error { _, err := w.Write([]byte{Version, 0x00}) return err }