v3

package
v0.0.0-...-3f6b1f2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 26, 2025 License: Apache-2.0 Imports: 18 Imported by: 0

Documentation

Index

Constants

View Source
const (
	DatagramPayloadHeaderLen = datagramTypeLen + datagramRequestIdLen
)

Variables

View Source
var (
	ErrInvalidDatagramType                 error = errors.New("invalid datagram type expected")
	ErrDatagramHeaderTooSmall              error = fmt.Errorf("datagram should have at least %d byte", datagramTypeLen)
	ErrDatagramPayloadTooLarge             error = errors.New("payload length is too large to be bundled in datagram")
	ErrDatagramPayloadHeaderTooSmall       error = errors.New("payload length is too small to fit the datagram header")
	ErrDatagramPayloadInvalidSize          error = errors.New("datagram provided is an invalid size")
	ErrDatagramResponseMsgInvalidSize      error = errors.New("datagram response message is an invalid size")
	ErrDatagramResponseInvalidSize         error = errors.New("datagram response is an invalid size")
	ErrDatagramResponseMsgTooLargeMaximum  error = fmt.Errorf("datagram response error message length exceeds the length of the datagram maximum: %d", maxResponseErrorMessageLen)
	ErrDatagramResponseMsgTooLargeDatagram error = fmt.Errorf("datagram response error message length exceeds the length of the provided datagram")
	ErrDatagramICMPPayloadTooLarge         error = fmt.Errorf("datagram icmp payload exceeds %d bytes", maxICMPPayloadLen)
	ErrDatagramICMPPayloadMissing          error = errors.New("datagram icmp payload is missing")
)
View Source
var (
	// ErrSessionNotFound indicates that a session has not been registered yet for the request id.
	ErrSessionNotFound = errors.New("flow not found")
	// ErrSessionBoundToOtherConn is returned when a registration already exists for a different connection.
	ErrSessionBoundToOtherConn = errors.New("flow is in use by another connection")
	// ErrSessionAlreadyRegistered is returned when a registration already exists for this connection.
	ErrSessionAlreadyRegistered = errors.New("flow is already registered for this connection")
	// ErrSessionRegistrationRateLimited is returned when a registration fails due to rate limiting on the number of active flows.
	ErrSessionRegistrationRateLimited = errors.New("flow registration rate limited")
)
View Source
var (
	// ErrInvalidRequestIDLen is returned when the provided request id can not be parsed from the provided byte slice.
	ErrInvalidRequestIDLen error = errors.New("invalid request id length provided")
	// ErrInvalidPayloadDestLen is returned when the provided destination byte slice cannot fit the whole request id.
	ErrInvalidPayloadDestLen error = errors.New("invalid payload size provided")
)
View Source
var SessionCloseErr error = errors.New("flow was closed directly")

SessionCloseErr indicates that the session's Close method was called.

Functions

func MarshalPayloadHeaderTo

func MarshalPayloadHeaderTo(requestID RequestID, payload []byte) error

MarshalPayloadHeaderTo provides a way to insert the Session Payload header into an already existing byte slice without having to allocate and copy the payload into the destination.

This method should be used in-place of MarshalBinary which will allocate in-place the required byte array to return.

Types

type DatagramConn

type DatagramConn interface {
	DatagramUDPWriter
	DatagramICMPWriter
	// Serve provides a server interface to process and handle incoming QUIC datagrams and demux their datagram v3 payloads.
	Serve(context.Context) error
	// ID indicates connection index identifier
	ID() uint8
}

DatagramConn is the bridge that multiplexes writes and reads of datagrams for UDP sessions and ICMP packets to a connection.

func NewDatagramConn

func NewDatagramConn(conn QuicConnection, sessionManager SessionManager, icmpRouter ingress.ICMPRouter, index uint8, metrics Metrics, logger *zerolog.Logger) DatagramConn

type DatagramICMPWriter

type DatagramICMPWriter interface {
	SendICMPPacket(icmp *packet.ICMP) error
	SendICMPTTLExceed(icmp *packet.ICMP, rawPacket packet.RawPacket) error
}

DatagramICMPWriter provides the Muxer interface to create ICMP Datagrams when sending over a connection.

type DatagramType

type DatagramType byte
const (
	// UDP Registration
	UDPSessionRegistrationType DatagramType = 0x0
	// UDP Session Payload
	UDPSessionPayloadType DatagramType = 0x1
	// DatagramTypeICMP (supporting both ICMPv4 and ICMPv6)
	ICMPType DatagramType = 0x2
	// UDP Session Registration Response
	UDPSessionRegistrationResponseType DatagramType = 0x3
)

func ParseDatagramType

func ParseDatagramType(data []byte) (DatagramType, error)

type DatagramUDPWriter

type DatagramUDPWriter interface {
	SendUDPSessionDatagram(datagram []byte) error
	SendUDPSessionResponse(id RequestID, resp SessionRegistrationResp) error
}

DatagramUDPWriter provides the Muxer interface to create proper UDP Datagrams when sending over a connection.

type DialUDP

type DialUDP func(dest netip.AddrPort) (*net.UDPConn, error)

type ICMPDatagram

type ICMPDatagram struct {
	Payload []byte
}

ICMPDatagram is used to propagate ICMPv4 and ICMPv6 payloads.

func (*ICMPDatagram) MarshalBinary

func (d *ICMPDatagram) MarshalBinary() (data []byte, err error)

func (*ICMPDatagram) UnmarshalBinary

func (d *ICMPDatagram) UnmarshalBinary(data []byte) error

type Metrics

type Metrics interface {
	IncrementFlows()
	DecrementFlows()
	PayloadTooLarge()
	RetryFlowResponse()
	MigrateFlow()
}

func NewMetrics

func NewMetrics(registerer prometheus.Registerer) Metrics

type QuicConnection

type QuicConnection interface {
	Context() context.Context
	SendDatagram(payload []byte) error
	ReceiveDatagram(context.Context) ([]byte, error)
}

QuicConnection provides an interface that matches [quic.Connection] for only the datagram operations.

We currently rely on the mutex for the [quic.Connection.SendDatagram] and [quic.Connection.ReceiveDatagram] and do not have any locking for them. If the implementation in quic-go were to ever change, we would need to make sure that we lock properly on these operations.

type RequestID

type RequestID uint128

RequestID is the request-id-v2 identifier, it is used to distinguish between specific flows or sessions proxied from the edge to cloudflared.

func RequestIDFromSlice

func RequestIDFromSlice(data []byte) (RequestID, error)

RequestIDFromSlice reads a request ID from a byte slice.

func (RequestID) Compare

func (id RequestID) Compare(id2 RequestID) int

Compare returns an integer comparing two IPs. The result will be 0 if id == id2, -1 if id < id2, and +1 if id > id2. The definition of "less than" is the same as the RequestID.Less method.

func (RequestID) Less

func (id RequestID) Less(id2 RequestID) bool

Less reports whether id sorts before id2.

func (RequestID) MarshalBinaryTo

func (id RequestID) MarshalBinaryTo(data []byte) error

MarshalBinaryTo writes the id to the provided destination byte slice; the byte slice must be of at least size 16.

func (RequestID) String

func (id RequestID) String() string

func (*RequestID) UnmarshalBinary

func (id *RequestID) UnmarshalBinary(data []byte) error

type Session

type Session interface {
	io.WriteCloser
	ID() RequestID
	ConnectionID() uint8
	RemoteAddr() net.Addr
	LocalAddr() net.Addr
	ResetIdleTimer()
	Migrate(eyeball DatagramConn, ctx context.Context, logger *zerolog.Logger)
	// Serve starts the event loop for processing UDP packets
	Serve(ctx context.Context) error
}

func NewSession

func NewSession(
	id RequestID,
	closeAfterIdle time.Duration,
	origin io.ReadWriteCloser,
	originAddr net.Addr,
	localAddr net.Addr,
	eyeball DatagramConn,
	metrics Metrics,
	log *zerolog.Logger,
) Session

type SessionIdleErr

type SessionIdleErr struct {
	// contains filtered or unexported fields
}

SessionIdleErr is returned when the session was closed because there was no communication in either direction over the session for the timeout period.

func (SessionIdleErr) Error

func (e SessionIdleErr) Error() string

func (SessionIdleErr) Is

func (e SessionIdleErr) Is(target error) bool

type SessionManager

type SessionManager interface {
	// RegisterSession will register a new session if it does not already exist for the request ID.
	// During new session creation, the session will also bind the UDP socket for the origin.
	// If the session exists for a different connection, it will return [ErrSessionBoundToOtherConn].
	RegisterSession(request *UDPSessionRegistrationDatagram, conn DatagramConn) (Session, error)
	// GetSession returns an active session if available for the provided connection.
	// If the session does not exist, it will return [ErrSessionNotFound]. If the session exists for a different
	// connection, it will return [ErrSessionBoundToOtherConn].
	GetSession(requestID RequestID) (Session, error)
	// UnregisterSession will remove a session from the current session manager. It will attempt to close the session
	// before removal.
	UnregisterSession(requestID RequestID)
}

func NewSessionManager

func NewSessionManager(metrics Metrics, log *zerolog.Logger, originDialer DialUDP, limiter cfdflow.Limiter) SessionManager

type SessionRegistrationResp

type SessionRegistrationResp byte

SessionRegistrationResp represents all of the responses that a UDP session registration response can return back to the client.

const (
	// Session was received and is ready to proxy.
	ResponseOk SessionRegistrationResp = 0x00
	// Session registration was unable to reach the requested origin destination.
	ResponseDestinationUnreachable SessionRegistrationResp = 0x01
	// Session registration was unable to bind to a local UDP socket.
	ResponseUnableToBindSocket SessionRegistrationResp = 0x02
	// Session registration failed due to the number of flows being higher than the limit.
	ResponseTooManyActiveFlows SessionRegistrationResp = 0x03
	// Session registration failed with an unexpected error but provided a message.
	ResponseErrorWithMsg SessionRegistrationResp = 0xff
)

type UDPSessionPayloadDatagram

type UDPSessionPayloadDatagram struct {
	RequestID RequestID
	Payload   []byte
}

UDPSessionPayloadDatagram provides the payload for a session to be send to either the origin or the client.

func (*UDPSessionPayloadDatagram) UnmarshalBinary

func (s *UDPSessionPayloadDatagram) UnmarshalBinary(data []byte) error

type UDPSessionRegistrationDatagram

type UDPSessionRegistrationDatagram struct {
	RequestID        RequestID
	Dest             netip.AddrPort
	Traced           bool
	IdleDurationHint time.Duration
	Payload          []byte
}

UDPSessionRegistrationDatagram handles a request to initialize a UDP session on the remote client.

func (*UDPSessionRegistrationDatagram) MarshalBinary

func (s *UDPSessionRegistrationDatagram) MarshalBinary() (data []byte, err error)

func (*UDPSessionRegistrationDatagram) UnmarshalBinary

func (s *UDPSessionRegistrationDatagram) UnmarshalBinary(data []byte) error

type UDPSessionRegistrationResponseDatagram

type UDPSessionRegistrationResponseDatagram struct {
	RequestID    RequestID
	ResponseType SessionRegistrationResp
	ErrorMsg     string
}

UDPSessionRegistrationResponseDatagram is used to either return a successful registration or error to the client that requested the registration of a UDP session.

func (*UDPSessionRegistrationResponseDatagram) MarshalBinary

func (s *UDPSessionRegistrationResponseDatagram) MarshalBinary() (data []byte, err error)

func (*UDPSessionRegistrationResponseDatagram) UnmarshalBinary

func (s *UDPSessionRegistrationResponseDatagram) UnmarshalBinary(data []byte) error

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL