Documentation
¶
Index ¶
- Constants
- Variables
- func ClientInitialKeysCalc(initialRandom []byte) (clientKey, clientIV, clientHpKey []byte, err error)
- func ComputeHeaderProtection(clientHpKey, sample []byte) ([]byte, error)
- func DecodeQUICHeaderAndFrames(p []byte) (hdr *QUICHeader, frames QUICFrames, err error)
- func DecodeVLI(vli []byte) (val uint64, err error)
- func DecryptAES128GCM(iv []byte, recordNum uint64, key, ciphertext, recdata, authtag []byte) (plaintext []byte, err error)
- func IsGREASETransportParameter(paramType uint64) bool
- func ReadNextVLI(r io.Reader) (val uint64, n int, err error)
- func ReassembleCRYPTOFrames(frames []QUICFrame) ([]byte, error)
- type CRYPTO
- type ClientHello
- type ClientInitial
- type FingerprintID
- type Framedeprecated
- type GatheredClientInitials
- func (gci *GatheredClientInitials) AddPacket(cip *ClientInitial) error
- func (gci *GatheredClientInitials) Completed() bool
- func (gci *GatheredClientInitials) Expired() bool
- func (gci *GatheredClientInitials) SetDeadline(deadline time.Time)
- func (gci *GatheredClientInitials) SetMaxPacketCount(maxPacketCount uint64)
- func (gci *GatheredClientInitials) SetMaxPacketNumber(maxPacketNumber uint64)
- func (gci *GatheredClientInitials) Wait() error
- type PADDING
- type PING
- type QUICClientHello
- type QUICClientHelloReconstructor
- func (qchr *QUICClientHelloReconstructor) AddCRYPTOFragment(offset uint64, frag []byte) error
- func (qr *QUICClientHelloReconstructor) FromFrames(frames []Frame) error
- func (qchr *QUICClientHelloReconstructor) Reconstruct() (*QUICClientHello, error)
- func (qchr *QUICClientHelloReconstructor) ReconstructAsBytes() []byte
- type QUICFingerprint
- type QUICFingerprinter
- func (qfp *QUICFingerprinter) Close()
- func (qfp *QUICFingerprinter) HandleIPConn(ipc *net.IPConn) error
- func (qfp *QUICFingerprinter) HandlePacket(from string, p []byte) error
- func (qfp *QUICFingerprinter) HandleUDPConn(pc net.PacketConn) error
- func (qfp *QUICFingerprinter) Peek(from string) *QUICFingerprint
- func (qfp *QUICFingerprinter) PeekAwait(from string) (*QUICFingerprint, error)
- func (qfp *QUICFingerprinter) Pop(from string) *QUICFingerprint
- func (qfp *QUICFingerprinter) PopAwait(from string) (*QUICFingerprint, error)
- func (qfp *QUICFingerprinter) SetTimeout(timeout time.Duration)
- type QUICFrame
- type QUICFrames
- type QUICHeader
- type QUICTransportParameters
- type TLSFingerprinter
- func (tfp *TLSFingerprinter) Close()
- func (tfp *TLSFingerprinter) HandleMessage(from string, p []byte) error
- func (tfp *TLSFingerprinter) HandleTCPConn(conn net.Conn) (rewindConn net.Conn, err error)
- func (tfp *TLSFingerprinter) Peek(from string) *ClientHello
- func (tfp *TLSFingerprinter) Pop(from string) *ClientHello
- func (tfp *TLSFingerprinter) SetTimeout(timeout time.Duration)
Constants ¶
const ( DEFAULT_MAX_INITIAL_PACKET_NUMBER uint64 = 32 DEFAULT_MAX_INITIAL_PACKET_COUNT uint64 = 4 )
const ( QUICFrame_PADDING uint64 = 0 // 0 QUICFrame_PING uint64 = 1 // 1 QUICFrame_CRYPTO uint64 = 6 // 6 )
const ( TOKEN_ABSENT uint32 = 0x00000000 TOKEN_PRESENT uint32 = 0x00000001 )
const ( QTP_GREASE = 27 UNSET_VLI_BITS = true // if false, unsetVLIBits() will be nop )
const DEFAULT_QUICFINGERPRINT_EXPIRY = 60 * time.Second
const DEFAULT_TLSFINGERPRINT_EXPIRY = 5 * time.Second
Variables ¶
var ( ErrGatheringExpired = errors.New("ClientInitials gathering has expired") ErrPacketRejected = errors.New("packet rejected based upon rules") ErrGatheredClientInitialsChannelClosedBeforeCompletion = errors.New("completion notification channel closed before setting completion flag") )
var ( ErrDuplicateFragment = errors.New("duplicate CRYPTO frame detected") ErrOverlapFragment = errors.New("overlap CRYPTO frame detected") ErrTooManyFragments = errors.New("too many CRYPTO fragments") ErrOffsetTooHigh = errors.New("offset too high") ErrNeedMoreFrames = errors.New("need more CRYPTO frames") )
var ( ErrNotQUICLongHeaderFormat = errors.New("not a QUIC Long Header Format Packet") ErrNotQUICInitialPacket = errors.New("not a QUIC Initial Packet") )
Functions ¶
func ClientInitialKeysCalc ¶
func ClientInitialKeysCalc(initialRandom []byte) (clientKey, clientIV, clientHpKey []byte, err error)
ClientInitialKeysCalc calculates the client key, IV and header protection key from the initial random.
func ComputeHeaderProtection ¶
ComputeHeaderProtection computes the header protection for the client.
func DecodeQUICHeaderAndFrames ¶
func DecodeQUICHeaderAndFrames(p []byte) (hdr *QUICHeader, frames QUICFrames, err error)
DecodeQUICHeaderAndFrames decodes a QUIC initial packet and returns a QUICHeader.
func DecryptAES128GCM ¶
func DecryptAES128GCM(iv []byte, recordNum uint64, key, ciphertext, recdata, authtag []byte) (plaintext []byte, err error)
DecryptAES128GCM decrypts the AES-128-GCM encrypted data.
func IsGREASETransportParameter ¶
IsGREASETransportParameter checks if the given transport parameter type is a GREASE value.
func ReadNextVLI ¶
ReadNextVLI unpacks the next variable-length integer from the given io.Reader. It returns the decoded value and the number of bytes read. For example:
0x0a -> 0xa, 1 0x80 0x10 0x00 0x00 -> 0x100000, 4
func ReassembleCRYPTOFrames ¶
ReassembleCRYPTOFrames reassembles CRYPTO frames into a single byte slice that consists of the entire CRYPTO data.
Types ¶
type CRYPTO ¶
type CRYPTO struct { Offset uint64 `json:"offset,omitempty"` // offset of crypto data, from VLI Length uint64 `json:"length,omitempty"` // length of crypto data, from VLI // contains filtered or unexported fields }
CRYPTO frame
type ClientHello ¶
type ClientHello struct { TLSRecordVersion uint16 `json:"tls_record_version"` // TLS record version (major, minor) TLSHandshakeVersion uint16 `json:"tls_handshake_version"` // TLS handshake version (major, minor) CipherSuites []uint16 `json:"cipher_suites"` CompressionMethods utils.Uint8Arr `json:"compression_methods"` Extensions []uint16 `json:"extensions"` // extension IDs in original order ExtensionsNormalized []uint16 `json:"extensions_normalized"` // sorted extension IDs ServerName string `json:"server_name"` // server_name(0) NamedGroupList []uint16 `json:"supported_groups"` // supported_groups(10) a.k.a elliptic_curves ECPointFormatList utils.Uint8Arr `json:"ec_point_formats"` // ec_point_formats(11) SignatureSchemeList []uint16 `json:"signature_algorithms"` // signature_algorithms(13) ALPN []string `json:"alpn"` // alpn(16) CertCompressAlgo []uint16 `json:"compress_certificate"` // compress_certificate(27) RecordSizeLimit utils.Uint8Arr `json:"record_size_limit"` // record_size_limit(28) SupportedVersions []uint16 `json:"supported_versions"` // supported_versions(43) PSKKeyExchangeModes utils.Uint8Arr `json:"psk_key_exchange_modes"` // psk_key_exchange_modes(45) ApplicationSettings []string `json:"application_settings"` // application_settings(17513) a.k.a ALPS UserAgent string `json:"user_agent,omitempty"` // User-Agent header, set by the caller NumID int64 `json:"num_id,omitempty"` // NID of the fingerprint NormNumID int64 `json:"norm_num_id,omitempty"` // Normalized NID of the fingerprint HexID string `json:"hex_id,omitempty"` // ID of the fingerprint (hex string) NormHexID string `json:"norm_hex_id,omitempty"` // Normalized ID of the fingerprint (hex string) // contains filtered or unexported fields }
ClientHello represents a captured ClientHello message with all fingerprintable fields.
func ReadClientHello ¶
func ReadClientHello(r io.Reader) (ch *ClientHello, err error)
ReadClientHello reads a ClientHello from a connection (io.Reader) and returns a ClientHello struct.
It will return an error if the reader does not give a stream of bytes representing a valid ClientHello. But all bytes read from the reader will be stored in the ClientHello struct to be rewinded by the caller if ever needed.
This function does not automatically call ClientHello.ParseClientHello.
func UnmarshalClientHello ¶
func UnmarshalClientHello(p []byte) (ch *ClientHello, err error)
UnmarshalClientHello unmarshals a ClientHello from a byte slice and returns a ClientHello struct. Any extra bytes after the ClientHello message will be ignored.
This function automatically calls ClientHello.ParseClientHello.
func (*ClientHello) ParseClientHello ¶
func (ch *ClientHello) ParseClientHello() error
ParseClientHello parses the raw bytes of a ClientHello into a ClientHello struct.
func (*ClientHello) Raw ¶
func (ch *ClientHello) Raw() []byte
type ClientInitial ¶
type ClientInitial struct { Header *QUICHeader `json:"header,omitempty"` // QUIC header FrameTypes []uint64 `json:"frames,omitempty"` // frames ID in order // contains filtered or unexported fields }
ClientInitial represents a QUIC Initial Packet sent by the Client.
func UnmarshalQUICClientInitialPacket ¶
func UnmarshalQUICClientInitialPacket(p []byte) (ci *ClientInitial, err error)
UnmarshalQUICClientInitialPacket is similar to ParseQUICCIP, but on error such as ClientHello cannot be parsed, it returns a partially completed ClientInitialPacket instead of nil.
type FingerprintID ¶
type FingerprintID int64
FingerprintID is the type of fingerprint ID.
func (FingerprintID) AsHex ¶
func (id FingerprintID) AsHex() string
AsHex returns the hex representation of this fingerprint ID.
type GatheredClientInitials ¶
type GatheredClientInitials struct { Packets []*ClientInitial `json:"packets,omitempty"` // sorted by ClientInitial.PacketNumber ClientHello *QUICClientHello `json:"client_hello,omitempty"` // TLS ClientHello TransportParameters *QUICTransportParameters `json:"transport_parameters,omitempty"` // QUIC Transport Parameters extracted from the extension in ClientHello HexID string `json:"hex_id,omitempty"` NumID uint64 `json:"num_id,omitempty"` // contains filtered or unexported fields }
GatheredClientInitials represents a series of Initial Packets sent by the Client to initiate the QUIC handshake.
func GatherClientInitials ¶
func GatherClientInitials() *GatheredClientInitials
GatherClientInitialPackets reads a series of Client Initial Packets from the input channel and returns the result of the gathered packets.
func GatherClientInitialsWithDeadline ¶
func GatherClientInitialsWithDeadline(deadline time.Time) *GatheredClientInitials
GatherClientInitialsWithDeadline is a helper function to create a GatheredClientInitials with a deadline.
func (*GatheredClientInitials) AddPacket ¶
func (gci *GatheredClientInitials) AddPacket(cip *ClientInitial) error
func (*GatheredClientInitials) Completed ¶
func (gci *GatheredClientInitials) Completed() bool
Completed returns true if the GatheredClientInitials is complete.
func (*GatheredClientInitials) Expired ¶
func (gci *GatheredClientInitials) Expired() bool
Expired returns true if the GatheredClientInitials has expired.
func (*GatheredClientInitials) SetDeadline ¶
func (gci *GatheredClientInitials) SetDeadline(deadline time.Time)
SetDeadline sets the deadline for the GatheredClientInitials to complete.
func (*GatheredClientInitials) SetMaxPacketCount ¶
func (gci *GatheredClientInitials) SetMaxPacketCount(maxPacketCount uint64)
SetMaxPacketCount sets the maximum number of packets to be gathered. If more Client Initial packets are received, they will be rejected.
This function can be used as a precaution against memory exhaustion attacks.
func (*GatheredClientInitials) SetMaxPacketNumber ¶
func (gci *GatheredClientInitials) SetMaxPacketNumber(maxPacketNumber uint64)
SetMaxPacketNumber sets the maximum packet number to be gathered. If a Client Initial packet with a higher packet number is received, it will be rejected.
This function can be used as a precaution against memory exhaustion attacks.
func (*GatheredClientInitials) Wait ¶
func (gci *GatheredClientInitials) Wait() error
Wait blocks until the GatheredClientInitials is complete or expired.
type PADDING ¶
type PADDING struct {
Length uint64 `json:"length,omitempty"` // count 0x00 bytes until not 0x00
}
PADDING frame
type QUICClientHello ¶
type QUICClientHello struct {
ClientHello
}
QUICClientHello represents a QUIC ClientHello.
func ParseQUICClientHello ¶
func ParseQUICClientHello(p []byte) (*QUICClientHello, error)
ParseQUICClientHello parses a QUIC ClientHello from a QUIC Initial Packet.
func (*QUICClientHello) Raw ¶
func (qch *QUICClientHello) Raw() []byte
Raw returns the raw bytes of the QUIC ClientHello.
type QUICClientHelloReconstructor ¶
type QUICClientHelloReconstructor struct {
// contains filtered or unexported fields
}
QUICClientHello can be used to parse fragments of a QUIC ClientHello.
func NewQUICClientHelloReconstructor ¶
func NewQUICClientHelloReconstructor() *QUICClientHelloReconstructor
NewQUICClientHelloReconstructor creates a new QUICClientHelloReconstructor.
func (*QUICClientHelloReconstructor) AddCRYPTOFragment ¶
func (qchr *QUICClientHelloReconstructor) AddCRYPTOFragment(offset uint64, frag []byte) error
AddCRYPTOFragment adds a CRYPTO frame fragment to the reconstructor. By default, all fragments are saved into an internal map as a pending fragment, UNLESS all fragments before it have been reassembled. If the fragment is the last one, it will return io.EOF.
func (*QUICClientHelloReconstructor) FromFrames ¶
func (qr *QUICClientHelloReconstructor) FromFrames(frames []Frame) error
FromFrames reassembles the ClientHello from the CRYPTO frames
func (*QUICClientHelloReconstructor) Reconstruct ¶
func (qchr *QUICClientHelloReconstructor) Reconstruct() (*QUICClientHello, error)
Reconstruct reassembles the ClientHello as a QUICClientHello struct.
func (*QUICClientHelloReconstructor) ReconstructAsBytes ¶
func (qchr *QUICClientHelloReconstructor) ReconstructAsBytes() []byte
ReconstructAsBytes reassembles the ClientHello as bytes.
type QUICFingerprint ¶
type QUICFingerprint struct { ClientInitials *GatheredClientInitials HexID string `json:"hex_id,omitempty"` NumID uint64 `json:"num_id,omitempty"` UserAgent string `json:"user_agent,omitempty"` // User-Agent header, set by the caller }
QUICFingerprint can be used to generate a fingerprint of a QUIC connection.
func GenerateQUICFingerprint ¶
func GenerateQUICFingerprint(gci *GatheredClientInitials) (*QUICFingerprint, error)
GenerateQUICFingerprint generates a QUICFingerprint from the gathered ClientInitials.
type QUICFingerprinter ¶
type QUICFingerprinter struct {
// contains filtered or unexported fields
}
QUICFingerprinter can be used to fingerprint QUIC connections.
func NewQUICFingerprinter ¶
func NewQUICFingerprinter() *QUICFingerprinter
NewQUICFingerprinter creates a new QUICFingerprinter.
func NewQUICFingerprinterWithTimeout ¶
func NewQUICFingerprinterWithTimeout(timeout time.Duration) *QUICFingerprinter
NewQUICFingerprinterWithTimeout creates a new QUICFingerprinter with a timeout.
func (*QUICFingerprinter) Close ¶
func (qfp *QUICFingerprinter) Close()
Close closes the QUICFingerprinter.
func (*QUICFingerprinter) HandleIPConn ¶
func (qfp *QUICFingerprinter) HandleIPConn(ipc *net.IPConn) error
HandleIPConn handles a QUIC connection over IP.
func (*QUICFingerprinter) HandlePacket ¶
func (qfp *QUICFingerprinter) HandlePacket(from string, p []byte) error
HandlePacket handles a QUIC packet.
func (*QUICFingerprinter) HandleUDPConn ¶
func (qfp *QUICFingerprinter) HandleUDPConn(pc net.PacketConn) error
HandleUDPConn handles a QUIC connection over UDP.
func (*QUICFingerprinter) Peek ¶
func (qfp *QUICFingerprinter) Peek(from string) *QUICFingerprint
Peek looks up a QUICFingerprint for a given key.
func (*QUICFingerprinter) PeekAwait ¶
func (qfp *QUICFingerprinter) PeekAwait(from string) (*QUICFingerprint, error)
PeekAwait looks up a QUICFingerprint for a given key. It will wait for the gathering to complete if the key exists but the gathering is not yet complete, e.g., when CRYPTO frames spread across multiple initial packets and some but not all of them are received.
func (*QUICFingerprinter) Pop ¶
func (qfp *QUICFingerprinter) Pop(from string) *QUICFingerprint
Pop looks up a QUICFingerprint for a given key and deletes it from the fingerprinter if found.
func (*QUICFingerprinter) PopAwait ¶
func (qfp *QUICFingerprinter) PopAwait(from string) (*QUICFingerprint, error)
PopAwait looks up a QUICFingerprint for a given key and deletes it from the fingerprinter if found. It will wait for the gathering to complete if the key exists but the gathering is not yet complete, e.g., when CRYPTO frames spread across multiple initial packets and some but not all of them are received.
func (*QUICFingerprinter) SetTimeout ¶
func (qfp *QUICFingerprinter) SetTimeout(timeout time.Duration)
SetTimeout sets the timeout for gathering ClientInitials.
type QUICFrame ¶
type QUICFrame interface { // FrameType returns the type of the frame. FrameType() uint64 // ReadReader takes a Reader and reads the rest of the frame from it, // starting from the first byte after the frame type. // // The returned io.Reader contains the rest of the frame, it could be // the input Reader itself (if no extra bytes are read) or a rewinded // Reader (if extra bytes are read and rewinding is needed). ReadReader(io.Reader) (io.Reader, error) }
QUICFrame is the interface that wraps the basic methods of a QUIC frame.
type QUICFrames ¶
type QUICFrames []QUICFrame
QUICFrames is a slice of QUICFrame.
func (QUICFrames) FrameTypes ¶
func (qfs QUICFrames) FrameTypes() []uint64
FrameTypes returns the frame types of all QUIC frames.
func (QUICFrames) FrameTypesUint8 ¶
func (qfs QUICFrames) FrameTypesUint8() []uint8
FrameTypesUint8 returns the frame types of all QUIC frames as uint8.
type QUICHeader ¶
type QUICHeader struct { Version utils.Uint8Arr `json:"version,omitempty"` // 4-byte version DCIDLength uint32 `json:"dest_conn_id_len,omitempty"` SCIDLength uint32 `json:"source_conn_id_len,omitempty"` PacketNumber utils.Uint8Arr `json:"packet_number,omitempty"` // VLI HasToken bool `json:"token,omitempty"` // contains filtered or unexported fields }
QUICHeader includes header fields of a QUIC packet and the following frames. It is used to calculate the fingerprint of a QUIC Header.
type QUICTransportParameters ¶
type QUICTransportParameters struct { MaxIdleTimeout utils.Uint8Arr `json:"max_idle_timeout,omitempty"` MaxUDPPayloadSize utils.Uint8Arr `json:"max_udp_payload_size,omitempty"` InitialMaxData utils.Uint8Arr `json:"initial_max_data,omitempty"` InitialMaxStreamDataBidiLocal utils.Uint8Arr `json:"initial_max_stream_data_bidi_local,omitempty"` InitialMaxStreamDataBidiRemote utils.Uint8Arr `json:"initial_max_stream_data_bidi_remote,omitempty"` InitialMaxStreamDataUni utils.Uint8Arr `json:"initial_max_stream_data_uni,omitempty"` InitialMaxStreamsBidi utils.Uint8Arr `json:"initial_max_streams_bidi,omitempty"` InitialMaxStreamsUni utils.Uint8Arr `json:"initial_max_streams_uni,omitempty"` AckDelayExponent utils.Uint8Arr `json:"ack_delay_exponent,omitempty"` MaxAckDelay utils.Uint8Arr `json:"max_ack_delay,omitempty"` ActiveConnectionIDLimit utils.Uint8Arr `json:"active_connection_id_limit,omitempty"` QTPIDs []uint64 `json:"tpids,omitempty"` // sorted HexID string `json:"hex_id,omitempty"` NumID uint64 `json:"num_id,omitempty"` // contains filtered or unexported fields }
QUICTransportParameters is a struct to hold the parsed QUIC transport parameters as a combination.
func ParseQUICTransportParameters ¶
func ParseQUICTransportParameters(extData []byte) *QUICTransportParameters
ParseQUICTransportParameters parses the transport parameters from the extension data of TLS Extension "QUIC Transport Parameters" (57)
If any error occurs, the returned struct will have parseError set to the error.
func (*QUICTransportParameters) ParseError ¶
func (qtp *QUICTransportParameters) ParseError() error
ParseError returns the error that occurred during parsing, if any.
type TLSFingerprinter ¶
type TLSFingerprinter struct {
// contains filtered or unexported fields
}
TLSFingerprinter can be used to fingerprint TLS connections.
func NewTLSFingerprinter ¶
func NewTLSFingerprinter() *TLSFingerprinter
NewTLSFingerprinter creates a new TLSFingerprinter.
func NewTLSFingerprinterWithTimeout ¶
func NewTLSFingerprinterWithTimeout(timeout time.Duration) *TLSFingerprinter
NewTLSFingerprinterWithTimeout creates a new TLSFingerprinter with a timeout.
func (*TLSFingerprinter) Close ¶
func (tfp *TLSFingerprinter) Close()
Close closes the TLSFingerprinter.
func (*TLSFingerprinter) HandleMessage ¶
func (tfp *TLSFingerprinter) HandleMessage(from string, p []byte) error
HandleMessage handles a message.
func (*TLSFingerprinter) HandleTCPConn ¶
HandleTCPConn handles a TCP connection.
func (*TLSFingerprinter) Peek ¶
func (tfp *TLSFingerprinter) Peek(from string) *ClientHello
Peek looks up a ClientHello for a given key.
func (*TLSFingerprinter) Pop ¶
func (tfp *TLSFingerprinter) Pop(from string) *ClientHello
Pop looks up a ClientHello for a given key and deletes it from the fingerprinter if found.
func (*TLSFingerprinter) SetTimeout ¶
func (tfp *TLSFingerprinter) SetTimeout(timeout time.Duration)
SetTimeout sets the timeout for the TLSFingerprinter.