fastdns

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jun 28, 2025 License: Apache-2.0 Imports: 16 Imported by: 0

README

FastDNS

GoDoc

fastdns is a high-performance DNS client for Go. It leverages Linux XDP sockets for ultra-low-latency, lock-free DNS queries, bypassing the kernel network stack for maximum throughput.

Install

go get github.com/dwisiswant0/fastdns@latest

[!NOTE] This library requires CAP_NET_ADMIN capability or root privileges to create & manage XDP sockets and attach programs to network interfaces.

Example

package main

import (
    "fmt"
    "net"

    "github.com/dwisiswant0/fastdns"
    "github.com/miekg/dns"
)

func main() {
	// Define the DNS resolver to use.
	// This should be a valid IP address of a DNS resolver.
	resolver := net.ParseIP("1.1.1.1")

	// Create a new FastDNS instance with the default resolver.
	f, err := fastdns.New(resolver)
	if err != nil {
		panic(err)
	}

	// Ensure that the FastDNS instance is closed when done.
	// Closing is essential to properly release all underlying XDP and socket
	// resources.
	//
	// If Close is not called, system resources such as file descriptors and
	// network handles may be leaked, which can eventually exhaust available
	// resources and cause failures in network operations or prevent new FastDNS
	// instances from being created.
	defer f.Close()

	// Create a new DNS query message.
	msg := new(dns.Msg)
	msg.SetQuestion(dns.Fqdn("cloudflare.com"), dns.TypeA)

	// Send the DNS query and receive the response.
	resp, _, err := f.Query(msg)
	if err != nil {
		f.Close()

		panic(err)
	}

	fmt.Printf("Response: %v\n", resp.String())
	fmt.Printf("Round-trip time: %v\n", rtt)
}

Status

[!CAUTION] fastdns has NOT reached 1.0 yet. Therefore, this library is currently not supported and does not offer a stable API; use at your own risk.

There are no guarantees of stability for the APIs in this library, and while they are not expected to change dramatically. API tweaks and bug fixes may occur.

License

fastdns is released by @dwisiswant0 under the Apache 2.0 license. See LICENSE.

Documentation

Index

Examples

Constants

View Source
const (
	// DefaultTimeout is the default timeout for DNS queries.
	DefaultTimeout = 5 * time.Second

	// DefaultMaxRetries is the default maximum number of retries for DNS
	// queries.
	DefaultMaxRetries = 3

	// DefaultQueueID is the default queue ID for sending DNS packets.
	DefaultQueueID = 0

	// DefaultCacheTTL is the default time-to-live for cached DNS responses.
	DefaultCacheTTL = 1 * time.Minute

	// DefaultCacheCapacity is the default capacity for the DNS response cache.
	DefaultCacheCapacity = 1000
)

Variables

View Source
var (
	ErrARPEntryMissing          = errors.New("ARP entry might be missing or stale")
	ErrInvalidFile              = errors.New("could not read file")
	ErrInvalidIPAddr            = errors.New("invalid IP address")
	ErrInvalidMACAddr           = errors.New("invalid MAC address")
	ErrInvalidPacketDestination = errors.New("packet not destined for us or not from DNS server")
	ErrInvalidQueueID           = errors.New("invalid queue ID")
	ErrInvalidTimeout           = errors.New("invalid timeout")
	ErrInvalidXDPSocket         = errors.New("missing or invalid XDP socket")
	ErrNoDefaultRoute           = errors.New("could not determine default route")
	ErrNoDestMACAddr            = errors.New("could not find a valid/reachable MAC address")
	ErrNoDNSResponse            = errors.New("no DNS response")
	ErrNoDstIP                  = errors.New("could not determine destination IP")
	ErrNoFile                   = errors.New("no file provided")
	ErrNoIPLayer                = errors.New("could not get IP layer")
	ErrNoIPv4Addr               = errors.New("could not get IPv4 address")
	ErrNoLink                   = errors.New("could not get link")
	ErrNoMACAddr                = errors.New("could not get MAC address")
	ErrNoMapperFunc             = errors.New("no mapper function provided")
	ErrNoNeighbors              = errors.New("could not list neighbors")
	ErrNoNextHopIP              = errors.New("could not determine next hop IP")
	ErrNoQueries                = errors.New("no queries provided")
	ErrNoSuitableIPv4Addr       = errors.New("no suitable IPv4 address found")
	ErrNoTXDescriptors          = errors.New("could not get TX descriptors")
	ErrNoUDPLayer               = errors.New("could not get UDP layer")
	ErrPacketTooSmall           = errors.New("packet too small")
	ErrPoll                     = errors.New("poll error")
	ErrRootRequired             = errors.New("CAP_NET_ADMIN capability or root privileges required")
)

Functions

This section is empty.

Types

type FastDNS

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

FastDNS holds all state and resources required for high-performance DNS queries using XDP sockets. It manages network interface details, link-layer addressing, serialization buffers, and DNS response caching.

func New

func New(dstIP net.IP, opts ...FastDNSOption) (*FastDNS, error)

New creates a new FastDNS instance with the given destination IP address and optional configuration options. It returns an error if the destination IP address is not set or if any of the configuration options are invalid. It also sets up the XDP program and socket for sending and receiving DNS queries.

func (*FastDNS) Close

func (f *FastDNS) Close() error

Close cleans up XDP sockets and programs. It is essential to call Close when you are done using FastDNS to prevent resource leaks. Failing to close may leave file descriptors, network handles, and kernel resources open, which can eventually exhaust system resources, cause failures in network operations, or prevent new FastDNS instances from being created.

func (*FastDNS) Queries

func (f *FastDNS) Queries(msgs ...*dns.Msg) ([]*Response, error)

Queries sends multiple DNS queries and returns their responses. It serializes each DNS message, transmits them, and waits for replies. If caching is enabled, it checks for cached responses before sending. On success, it returns a slice of Response structs with the DNS responses and their round-trip times (RTT). On failure or timeout, it returns an error.

func (*FastDNS) Query

func (f *FastDNS) Query(msg *dns.Msg) *Response

Query sends a DNS query using the XDP socket and returns the response. It serializes the DNS message, transmits it, and waits for a reply. If caching is enabled, it checks for a cached response before sending. On success, it returns the DNS response and round-trip time (RTT). On failure or timeout, it returns an error in the Response struct.

Example

ExampleQuery demonstrates how to use the FastDNS library to send a DNS query. It creates a new FastDNS instance, sends a DNS query for the A record of "cloudflare.com", and prints the response.

This example assumes that you have a working network connection and that the FastDNS library is properly installed and configured. It also assumes that the DNS resolver is reachable and responds to the query.

package main

import (
	"fmt"
	"net"
	"os"

	"github.com/dwisiswant0/fastdns"
	"github.com/miekg/dns"
)

func main() {
	// Define the DNS resolver to use.
	// This should be a valid IP address of a DNS resolver.
	resolver := net.ParseIP("1.1.1.1")

	// Create a new FastDNS instance with the default resolver.
	f, err := fastdns.New(resolver)
	if err != nil {
		panic(err)
	}

	// Ensure that the FastDNS instance is closed when done.
	// Closing is essential to properly release all underlying XDP and socket
	// resources.
	//
	// If Close is not called, system resources such as file descriptors and
	// network handles may be leaked, which can eventually exhaust available
	// resources and cause failures in network operations or prevent new FastDNS
	// instances from being created.
	defer func() {
		if err := f.Close(); err != nil {
			fmt.Fprintf(os.Stderr, "Error during cleanup: %v\n", err)
		}
	}()

	// Create a new DNS query message.
	msg := new(dns.Msg)
	msg.SetQuestion(dns.Fqdn("cloudflare.com"), dns.TypeA)

	// Send the DNS query and receive the response.
	resp := f.Query(msg)
	if err := resp.Err(); err != nil {
		_ = f.Close()

		panic(err)
	}

	// Print the response.
	for _, answer := range resp.Message.Answer {
		println(answer.String())
	}
}

func (*FastDNS) QueryFromFile

func (f *FastDNS) QueryFromFile(file *os.File, mapper func(s string) *dns.Msg) ([]*Response, error)

QueryFromFile reads entries from a file and performs DNS queries using a custom mapper function. Each line in the file is processed by the mapper function to create DNS messages.

The mapper function takes a string from the file and returns a dns.Msg. This allows for custom DNS message creation based on the file content. If the mapper returns nil, that entry is skipped.

func (*FastDNS) Stats

func (f *FastDNS) Stats() (xdp.Stats, error)

Stats returns statistics about the XDP socket's ring queue usage and kernel interactions. This information can be useful for monitoring the performance and health of the XDP socket and the underlying network interface. The statistics are returned as an xdp.Stats struct, which contains various metrics related to the XDP socket's operation.

type FastDNSOption

type FastDNSOption func(*FastDNS)

FastDNSOption is a functional option for configuring FastDNS.

func WithAllowNonGlobalIPs

func WithAllowNonGlobalIPs() FastDNSOption

WithAllowNonGlobalIPs allows FastDNS to use non-global-unicast IPv4 addresses (such as loopback, multicast, or link-local) for source and destination IPs. By default, only global unicast addresses are allowed.

func WithCacheCapacity

func WithCacheCapacity(capacity int) FastDNSOption

WithCacheCapacity sets the capacity for the DNS response cache. This is the maximum number of DNS responses that FastDNS will keep in the cache. The capacity should be a valid integer. If not set, the default capacity will be used. The default capacity is defined in the DefaultCacheCapacity constant.

func WithCacheTTL

func WithCacheTTL(ttl time.Duration) FastDNSOption

WithCacheTTL sets the time-to-live (TTL) for cached DNS responses. This is the maximum time that FastDNS will keep a DNS response in the cache. The TTL should be a valid time.Duration object. If not set, the default TTL will be used. The default TTL is defined in the DefaultCacheTTL constant.

func WithDstLink(link Link) FastDNSOption

WithDstLink sets the destination link for FastDNS. This is the link that will be used to receive DNS responses. It is typically the link that is used to receive DNS responses. The link should be a valid Link object with a valid IP and MAC address. If not set, the default link will be used. The default link is determined by the system's routing table.

func WithMaxBatchSize

func WithMaxBatchSize(size int) FastDNSOption

WithMaxBatchSize sets the maximum batch size for DNS queries. This is the maximum number of DNS queries that FastDNS will send in a single batch. If not set, the batch size will be determined dynamically based on the number of free TX slots available.

func WithMaxRetries

func WithMaxRetries(retries int) FastDNSOption

WithMaxRetries sets the maximum number of retries for DNS queries. This is the maximum number of times that FastDNS will retry a DNS query if it fails. The number of retries should be a valid integer. If not set, the default number of retries will be used. The default number of retries is defined in the DefaultMaxRetries constant.

func WithNIC

func WithNIC(nic string) FastDNSOption

WithNIC sets the network interface card (NIC) for FastDNS. This is the NIC that will be used to send and receive DNS packets. The NIC should be a valid string representing the name of the network interface. If not set, the default NIC will be used. The default NIC is determined by the system's routing table.

func WithNoCache

func WithNoCache() FastDNSOption

WithNoCache disables the DNS response cache. If set, FastDNS will not cache any DNS responses. This is useful for testing or debugging purposes. If not set, the cache will be enabled by default. The default behavior is to cache DNS responses.

func WithProgram

func WithProgram(program *xdp.Program) FastDNSOption

WithProgram sets the XDP program for FastDNS. This is the program that will be used to process DNS packets. The program should be a valid xdp.Program object. If not set, the default program will be used.

func WithQueueID

func WithQueueID(queueID int) FastDNSOption

WithQueueID sets the queue ID for FastDNS. This is the queue that will be used to send DNS packets. The queue ID should be a valid integer. If not set, the default queue ID (0) will be used.

func WithSocket

func WithSocket(socket *xdp.Socket) FastDNSOption

WithSocket sets the XDP socket for FastDNS. This is the socket that will be used to send and receive DNS packets. The socket should be a valid xdp.Socket object. If not set, the default socket will be used.

func WithSocketOptions

func WithSocketOptions(options *xdp.SocketOptions) FastDNSOption

WithSocketOptions sets the XDP socket options for FastDNS. These options control the behavior of the socket. The options should be a valid xdp.SocketOptions object. If not set, the default options will be used. The default options are defined in the xdp.DefaultSocketOptions variable.

func WithSrcLink(link Link) FastDNSOption

WithSrcLink sets the source link for FastDNS. This is the link that will be used to send DNS queries. It is typically the link that is used to reach the DNS resolver. The link should be a valid Link object with a valid IP and MAC address. If not set, the default link will be used. The default link is determined by the system's routing table.

func WithTimeout

func WithTimeout(timeout time.Duration) FastDNSOption

WithTimeout sets the timeout for DNS queries. This is the maximum time that FastDNS will wait for a DNS response. The timeout should be a valid time.Duration object. If not set, the default timeout will be used. The default timeout is defined in the DefaultTimeout constant.

type Link struct {
	// IP is the IP address of the link.
	IP net.IP

	// MAC is the MAC address of the link.
	MAC net.HardwareAddr
}

Link represents a network link with its IP and MAC address.

type Response

type Response struct {
	Error error `json:"error"`

	// Message is the DNS message received from the server.
	Message *dns.Msg `json:"message"`

	// RTT is the round-trip time for the DNS query.
	// It represents the duration from sending the query to receiving the
	// response.
	//
	// RTT is set to -1 when there is no response or the query fails.
	// RTT is set to 0 when the response is served from cache.
	// Otherwise, RTT is set to the actual time taken for the query.
	RTT time.Duration `json:"rtt"`
	// contains filtered or unexported fields
}

Response represents the result of a DNS query.

func (*Response) Err

func (r *Response) Err() error

Err returns the error associated with the [Result]. If there is no error, it returns nil. If there is an error, it returns the error.

func (*Response) IsError

func (r *Response) IsError() bool

IsError checks if the [Result] contains an error. It returns true if there is an error, and false otherwise. This is useful for checking if the DNS query was successful or not. If there is no error, it returns false. If there is an error, it returns true.

func (*Response) IsSuccess

func (r *Response) IsSuccess() bool

IsSuccess checks if the [Result] is successful. It returns true if there is no error and the Message is not nil. This is useful for checking if the DNS query was successful. If there is an error, it returns false. If the Message is nil, it returns false. If the Message is not nil and there is no error, it returns true.

func (*Response) MarshalJSON

func (r *Response) MarshalJSON() ([]byte, error)

MarshalJSON marshals the [Result] into JSON format.

func (*Response) String

func (r *Response) String() string

String returns a string representation of the [Result]. If there is an error, it returns the error message. If there is no error and the Message is nil, it returns an empty string. If there is no error and the Message is not nil, it returns the string representation of the Message.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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