protocol

package
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: Jan 23, 2026 License: MIT Imports: 5 Imported by: 0

Documentation

Overview

Package protocol implements the wire protocol for DNS tunneling.

Index

Constants

View Source
const (
	// ALPN is the Application-Layer Protocol Negotiation identifier
	ALPN = "picoquic_sample"

	// SNI is the Server Name Indication used in TLS handshake
	SNI = "test.example.com"

	// InlineDotsInterval is the number of characters between inline dots in DNS labels
	// DNS labels have a maximum length of 63 characters, so we insert a dot every 57 chars
	// to stay well within the limit.
	InlineDotsInterval = 57

	// MaxDNSLabelLength is the maximum length of a DNS label (RFC 1035)
	MaxDNSLabelLength = 63

	// MaxDNSNameLength is the maximum length of a complete DNS name (RFC 1035)
	MaxDNSNameLength = 255

	// EDNS0UDPSize is the UDP payload size for EDNS0
	EDNS0UDPSize = 1232

	// DefaultClientPort is the default TCP port the client listens on
	DefaultClientPort = 5201

	// DefaultServerPort is the default DNS port the server listens on
	DefaultServerPort = 53

	// DefaultKeepAliveInterval is the default keep-alive interval in milliseconds
	DefaultKeepAliveInterval = 400

	// DummyAddress is the dummy source address used for path management (192.0.2.1)
	// This is from the TEST-NET-1 range (RFC 5737)
	DummyAddress = "192.0.2.1"

	// DummyPort is the dummy port used for path management
	DummyPort = 12345
)
View Source
const (
	NoError         = 0
	InternalError   = 0x101
	FileCancelError = 0x105
)

Error codes

View Source
const (
	// DNSQueryTypeA is the DNS query type for A records
	DNSQueryTypeA = 1

	// DNSQueryTypeAAAA is the DNS query type for AAAA records
	DNSQueryTypeAAAA = 28

	// DNSQueryTypeTXT is the DNS query type for TXT records
	DNSQueryTypeTXT = 16

	// DNSClassINET is the DNS class for Internet
	DNSClassINET = 1

	// DNSResponseCodeNoError indicates success
	DNSResponseCodeNoError = 0

	// DNSResponseCodeNXDomain indicates domain does not exist
	DNSResponseCodeNXDomain = 3

	// DNSResponseCodeServerFailure indicates server failure
	DNSResponseCodeServerFailure = 2
)

DNS-related constants

Variables

View Source
var (
	// ErrInvalidBase32 is returned when base32 decoding fails
	ErrInvalidBase32 = errors.New("invalid base32 encoding")

	// ErrInvalidEncoding is returned when the encoding is malformed
	ErrInvalidEncoding = errors.New("invalid encoding")
)
View Source
var (
	// ErrBufferTooSmall is returned when the buffer is too small to hold the dotified string
	ErrBufferTooSmall = errors.New("buffer too small for dotification")
)

Functions

func CalculateDotifiedLength

func CalculateDotifiedLength(length int) int

CalculateDotifiedLength calculates the length after dotification without actually performing the dotification. Useful for pre-allocating buffers.

func CalculateEncodedLength

func CalculateEncodedLength(dataLen int) int

CalculateEncodedLength calculates the length of the encoded domain name (without domain suffix) for a given data length. Useful for pre-allocating buffers.

func DecodeData

func DecodeData(encodedDomain string) ([]byte, error)

DecodeData decodes data from a DNS domain name. The decoding process: 1. Remove inline dots (undotify) 2. Base32 decode

Returns the decoded binary data.

func DecodeFromDNSName

func DecodeFromDNSName(queryName, domainSuffix string) ([]byte, error)

DecodeFromDNSName extracts and decodes data from a DNS query name. It removes the domain suffix and decodes the remaining data.

func Dotify

func Dotify(data []byte) ([]byte, error)

Dotify inserts dots every 57 characters in the input string for DNS label compliance. DNS labels have a maximum length of 63 characters, so inserting dots at 57-char intervals ensures we stay within the limit.

The function works in-place when possible, modifying the input buffer and returning the dotified portion. If the input is a string, it returns a new string.

Example: "A"*57 + "B"*57 becomes "A"*57 + "." + "B"*57

func DotifyInPlace

func DotifyInPlace(buf []byte, length int) (int, error)

DotifyInPlace dotifies a byte slice in place, expanding it to accommodate dots. The caller must ensure the buffer has enough capacity (len + len/57 bytes). Returns the new length or an error if the buffer is too small.

func EncodeData

func EncodeData(data []byte) (string, error)

EncodeData encodes binary data for transmission in DNS queries. The encoding process: 1. Base32 encode the data (no padding) 2. Insert inline dots every 57 characters 3. Add domain suffix

Returns the encoded domain name (without the final domain suffix).

func EncodeToDNSName

func EncodeToDNSName(data []byte, domainSuffix string) (string, error)

EncodeToDNSName encodes binary data and appends the domain suffix. Example: data → base32 → dotified → "dotified.example.com"

func MaxDataLengthForDNSName

func MaxDataLengthForDNSName(maxDNSLen int, domainSuffixLen int) int

MaxDataLengthForDNSName calculates the maximum data length that can be encoded in a DNS name of the given length (including domain suffix).

DNS names have a maximum length of 255 characters.

func Undotify

func Undotify(data []byte) []byte

Undotify removes all dots from the input data. This is the reverse operation of Dotify.

The function works in-place, modifying the input buffer and returning the undotified portion.

func UndotifyString

func UndotifyString(s string) string

UndotifyString removes all dots from a string and returns a new string.

Types

type Slot

type Slot struct {
	// DNSQuery is the raw DNS query data
	DNSQuery []byte

	// DNSResponse is the raw DNS response data (if any)
	DNSResponse []byte

	// PeerAddr is the address of the DNS client making the request
	PeerAddr net.Addr

	// LocalAddr is the local address that received the request
	LocalAddr net.Addr

	// ConnectionID is the QUIC connection ID associated with this slot
	ConnectionID []byte

	// PathID identifies which path this packet came from (for multipath)
	PathID int

	// IsPollPacket indicates if this is a poll packet (size 0, non-ACK-eliciting)
	IsPollPacket bool

	// Error indicates any error that occurred while processing
	Error error

	// Timestamp records when this slot was created
	Timestamp int64
}

Slot represents a DNS request/response pair with associated metadata. It tracks the connection, addresses, and whether this is a poll packet.

func (*Slot) Reset

func (s *Slot) Reset()

Reset clears all fields of the slot for reuse.

func (*Slot) SetConnectionID

func (s *Slot) SetConnectionID(id []byte)

SetConnectionID sets the connection ID, reusing the underlying buffer if possible.

func (*Slot) SetDNSQuery

func (s *Slot) SetDNSQuery(data []byte)

SetDNSQuery sets the DNS query data, reusing the underlying buffer if possible.

func (*Slot) SetDNSResponse

func (s *Slot) SetDNSResponse(data []byte)

SetDNSResponse sets the DNS response data, reusing the underlying buffer if possible.

type SlotPool

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

SlotPool manages a pool of reusable slots to reduce allocations.

func NewSlotPool

func NewSlotPool() *SlotPool

NewSlotPool creates a new slot pool.

func (*SlotPool) Get

func (p *SlotPool) Get() *Slot

Get retrieves a slot from the pool.

func (*SlotPool) Put

func (p *SlotPool) Put(s *Slot)

Put returns a slot to the pool.

type SlotQueue

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

SlotQueue is a FIFO queue for managing slots. Used by the server to queue DNS messages for processing.

func NewSlotQueue

func NewSlotQueue() *SlotQueue

NewSlotQueue creates a new slot queue.

func (*SlotQueue) Clear

func (q *SlotQueue) Clear()

Clear removes all slots from the queue.

func (*SlotQueue) Dequeue

func (q *SlotQueue) Dequeue() *Slot

Dequeue removes and returns the first slot from the queue. Blocks if the queue is empty.

func (*SlotQueue) Enqueue

func (q *SlotQueue) Enqueue(s *Slot)

Enqueue adds a slot to the queue.

func (*SlotQueue) Len

func (q *SlotQueue) Len() int

Len returns the current length of the queue.

func (*SlotQueue) TryDequeue

func (q *SlotQueue) TryDequeue() *Slot

TryDequeue attempts to dequeue a slot without blocking. Returns nil if the queue is empty.

Jump to

Keyboard shortcuts

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