Documentation
¶
Overview ¶
Package protocol implements the wire protocol for DNS tunneling.
Index ¶
- Constants
- Variables
- func CalculateDotifiedLength(length int) int
- func CalculateEncodedLength(dataLen int) int
- func DecodeData(encodedDomain string) ([]byte, error)
- func DecodeFromDNSName(queryName, domainSuffix string) ([]byte, error)
- func Dotify(data []byte) ([]byte, error)
- func DotifyInPlace(buf []byte, length int) (int, error)
- func EncodeData(data []byte) (string, error)
- func EncodeToDNSName(data []byte, domainSuffix string) (string, error)
- func MaxDataLengthForDNSName(maxDNSLen int, domainSuffixLen int) int
- func Undotify(data []byte) []byte
- func UndotifyString(s string) string
- type Slot
- type SlotPool
- type SlotQueue
Constants ¶
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 )
const ( NoError = 0 InternalError = 0x101 FileCancelError = 0x105 )
Error codes
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 ¶
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") )
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 ¶
CalculateDotifiedLength calculates the length after dotification without actually performing the dotification. Useful for pre-allocating buffers.
func CalculateEncodedLength ¶
CalculateEncodedLength calculates the length of the encoded domain name (without domain suffix) for a given data length. Useful for pre-allocating buffers.
func DecodeData ¶
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 ¶
DecodeFromDNSName extracts and decodes data from a DNS query name. It removes the domain suffix and decodes the remaining data.
func Dotify ¶
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 ¶
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 ¶
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 ¶
EncodeToDNSName encodes binary data and appends the domain suffix. Example: data → base32 → dotified → "dotified.example.com"
func MaxDataLengthForDNSName ¶
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 ¶
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 ¶
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) SetConnectionID ¶
SetConnectionID sets the connection ID, reusing the underlying buffer if possible.
func (*Slot) SetDNSQuery ¶
SetDNSQuery sets the DNS query data, reusing the underlying buffer if possible.
func (*Slot) SetDNSResponse ¶
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.
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 (*SlotQueue) Dequeue ¶
Dequeue removes and returns the first slot from the queue. Blocks if the queue is empty.
func (*SlotQueue) TryDequeue ¶
TryDequeue attempts to dequeue a slot without blocking. Returns nil if the queue is empty.