dnsd

package
v0.0.0-...-6a97c18 Latest Latest
Warning

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

Go to latest
Published: Dec 19, 2024 License: MPL-2.0 Imports: 30 Imported by: 0

Documentation

Index

Constants

View Source
const (
	ForwarderTimeoutSec         = 1 * 2     // ForwarderTimeoutSec is the IO timeout for a round trip interaction with forwarders
	ClientTimeoutSec            = 30 * 2    // AnswerTimeoutSec is the IO timeout for a round trip interaction with DNS clients
	MaxPacketSize               = 9038      // Maximum acceptable UDP packet size
	BlacklistUpdateIntervalSec  = 12 * 3600 // Update ad-server blacklist at this interval
	BlacklistInitialDelaySec    = 120       // BlacklistInitialDelaySec is the number of seconds to wait for downloading blacklists for the first time.
	MinNameQuerySize            = 14        // If a query packet is shorter than this length, it cannot possibly be a name query.
	PublicIPRefreshIntervalSec  = 900       // PublicIPRefreshIntervalSec is how often the program places its latest public IP address into array of IPs that may query the server.
	BlackListDownloadTimeoutSec = 30        // BlackListDownloadTimeoutSec is the timeout to use when downloading blacklist hosts files.
	BlacklistMaxEntries         = 100000    // BlackListMaxEntries is the maximum number of entries to be accepted into black list after retireving them from public sources.
	// CommonResponseTTL is the TTL of outgoing authoritative response records.
	CommonResponseTTL = 60
	/*
		ToolboxCommandPrefix is a short string that indicates a TXT query is most likely toolbox command. Keep it short,
		as DNS query input has to be pretty short.
	*/
	ToolboxCommandPrefix = '_'

	// ProxyPrefix is the name prefix DNS clients need to put in front of their
	// address queries to send the query to the TCP-over-DNS proxy.
	ProxyPrefix = 't'
)
View Source
const (
	// EDNSBufferSize is the maximum DNS buffer size advertised to DNS clients.
	EDNSBufferSize = 1232
)
View Source
const (
	/*
		MaxNameEntriesToExtract is the maximum number of entries to be extracted from one instance of hosts file.
		The limit prevents an exceedingly long third party host file from taking too much memory.
	*/
	MaxNameEntriesToExtract = 50000
)
View Source
const (
	// MaxProxyConnectionLifetime is the maximum lifetime of a transmission
	// control. The transmission controls are unconditionally closed after this
	// duration.
	MaxProxyConnectionLifetime = 30 * time.Minute
)

Variables

View Source
var (
	// DefaultForwarders is a list of well tested, public, recursive DNS resolvers that must support both TCP and UDP for queries.
	// When DNS daemon's forwarders are left unspecified, it will use these default forwarders.
	// Operators of the DNS resolvers below claim to offer enhanced cyber security to some degree.
	// Having more addresses in the list helps to improve DNS server reliability, as each client query is handled by a random forwarder.
	DefaultForwarders = []string{

		"9.9.9.9:53",
		"149.112.112.112:53",

		"1.1.1.2:53",
		"1.0.0.2:53",

		"208.67.222.222:53",
		"208.67.220.220:53",

		"94.140.14.14:53",
		"94.140.15.15:53",
	}
)
View Source
var HostsFileURLs = []string{
	"http://winhelp2002.mvps.org/hosts.txt",
	"http://pgl.yoyo.org/adservers/serverlist.php?hostformat=hosts&showintro=0&mimetype=plaintext",
	"http://someonewhocares.org/hosts/hosts",
	"https://raw.githubusercontent.com/blocklistproject/Lists/master/ransomware.txt",
	"https://raw.githubusercontent.com/blocklistproject/Lists/master/scam.txt",
	"https://raw.githubusercontent.com/blocklistproject/Lists/master/tracking.txt",
}

HostsFileURLs is a collection of URLs where up-to-date ad/malware/spyware blacklist hosts files are published.

View Source
var Whitelist = []string{}/* 192 elements not displayed */

Whitelist is an array of domain names that often appear in black lists, but cause inconvenience when blocked. These names are removed from downloaded black lists.

Functions

func BuildBlackHoleAddrResponse

func BuildBlackHoleAddrResponse(header dnsmessage.Header, question dnsmessage.Question) ([]byte, error)

BuildBlackHoleAddrResponse constructs an A or AAAA address record response packet pointing to localhost, the record TTL is hard coded to 600 seconds.

func BuildIPv4AddrResponse

func BuildIPv4AddrResponse(header dnsmessage.Header, question dnsmessage.Question, record V4AddressRecord) ([]byte, error)

BuildIPv4AddrResponse constructs an IPv4 address record response. The record TTL is hard coded to 60 seconds.

func BuildIPv6AddrResponse

func BuildIPv6AddrResponse(header dnsmessage.Header, question dnsmessage.Question, record V6AddressRecord) ([]byte, error)

BuildIPv6AddrResponse constructs an IPv6 address record response. The record TTL is hard coded to 60 seconds.

func BuildMXResponse

func BuildMXResponse(header dnsmessage.Header, question dnsmessage.Question, records []*net.MX) ([]byte, error)

BuildMXResponse constructs an MX query response.

func BuildNSResponse

func BuildNSResponse(header dnsmessage.Header, question dnsmessage.Question, domainName string, record NSRecord, glueIP net.IP) ([]byte, error)

BuildNSResponse returns an NS record response.

func BuildSOAResponse

func BuildSOAResponse(header dnsmessage.Header, question dnsmessage.Question, mName, rName string) ([]byte, error)

BuildSOAResponse returns an SOA record response.

func BuildTCPOverDNSSegmentResponse

func BuildTCPOverDNSSegmentResponse(header dnsmessage.Header, question dnsmessage.Question, domainName string, seg tcpoverdns.Segment) ([]byte, error)

BuildTCPOverDNSSegmentResponse constructs a DNS query response packet that encapsulates a TCP-over-DNS segment.

func BuildTextResponse

func BuildTextResponse(name string, header dnsmessage.Header, question dnsmessage.Question, txt []string) ([]byte, error)

BuildTextResponse constructs a TXT record response packet.

func CountNameLabels

func CountNameLabels(in string) int

CountNameLabels returns the number of labels in the DNS name.

func DecodeDTMFCommandInput

func DecodeDTMFCommandInput(labels []string) (decodedCommand string)

DecodeDTMFCommandInput extracts an app command (that may contain DTMF sequences) from the input DNS query labels which exclude the domain name.

func DownloadAllBlacklists

func DownloadAllBlacklists(maxEntries int, logger *lalog.Logger) []string

DownloadAllBlacklists attempts to download all hosts files and return combined list of domain names to block. The special cases of white listed names are removed from return value.

func ExtractNamesFromHostsContent

func ExtractNamesFromHostsContent(content string) []string

ExtractNamesFromHostsContent extracts domain names from hosts file content. It will not return empty lines, comments, and potentially illegal domain names.

func MaxDownstreamSegmentLengthTXT

func MaxDownstreamSegmentLengthTXT(dnsHostName string) int

MaxDownstreamSegmentLengthTXT returns the maximum segment length appropriate for the downstream traffic direction for the DNS host name.

func MaxUpstreamSegmentLength

func MaxUpstreamSegmentLength(dnsHostName string) int

MaxUpstreamSegmentLength returns the maximum segment length appropriate for the upstream traffic direction for the DNS host name.

func TestServer

func TestServer(dnsd *Daemon, t testingstub.T)

TestServer contains the comprehensive test cases for both TCP and UDP DNS servers.

Types

type AddressRecord

type AddressRecord struct {
	Addresses     []string `json:"Addresses"`
	CanonicalName string   `json:"CanonicalName"`
	// contains filtered or unexported fields
}

AddressRecord represents an version-agnostic DNS address record that has either IP addresses or CNAME.

func (*AddressRecord) Exists

func (rec *AddressRecord) Exists() bool

func (*AddressRecord) Lint

func (rec *AddressRecord) Lint(ipNetwork string) error

Lint checks the record for errors, and modifies it in-place to conform to protocol requirements.

func (*AddressRecord) Shuffled

func (rec *AddressRecord) Shuffled() []net.IP

Shuffled returns a copy of the IP addresses shuffled in random order.

type CacheEntry

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

CacheEntry is a cached TCP-over-DNS query response.

type CustomRecord

type CustomRecord struct {
	A    V4AddressRecord `json:"A"`
	AAAA V6AddressRecord `json:"AAAA"`
	TXT  TextRecord      `json:"TXT"`
	MX   []*net.MX       `json:"MX"`
	NS   NSRecord        `json:"NS"`
}

CustomRecord defines various types of resource records for a complete DNS name (e.g. www.me.example.com).

func (*CustomRecord) Lint

func (dname *CustomRecord) Lint() error

Lint checks all records for errors, and modifies them in-place to conform to protocol requirements.

func (*CustomRecord) MXExists

func (dname *CustomRecord) MXExists() bool

type DNSRelay

type DNSRelay struct {
	// Config contains the parameters for the initiator of the proxy
	// connections to configure the remote transmission control.
	Config tcpoverdns.InitiatorConfig
	// Debug enables verbose logging for IO activities.
	Debug bool
	// RequestOTPSecret is a TOTP secret for authorising outgoing connection
	// requests.
	RequestOTPSecret string

	// DNSResolver is the address (ip:port) of the public recursive DNS resolver.
	DNSResolver string
	// DNSHostName is the host name of the TCP-over-DNS proxy server.
	DNSHostName string

	// ForwardTo is the address (ip:port) of the public recursive DNS resolver.
	ForwardTo string
	// TransactionMutex is for relay's client to obtain to ensure proper
	// serialisation of DNS request-response transactions.
	TransactionMutex *sync.Mutex
	// contains filtered or unexported fields
}

func (*DNSRelay) Initialise

func (relay *DNSRelay) Initialise(ctx context.Context) error

Initialise validates configuration parameters and initialises the internal state of the relay.

func (*DNSRelay) StartAndBlock

func (relay *DNSRelay) StartAndBlock() error

StartAndBlock starts the internal transmission control to act as a relay toward the DNS forwarder.

func (*DNSRelay) Stop

func (relay *DNSRelay) Stop()

Stop the relay.

func (*DNSRelay) TransmissionControl

func (relay *DNSRelay) TransmissionControl(ctx context.Context) *tcpoverdns.TransmissionControl

TransmissionControl waits for the proxied connection's transmission control to reach the establish state and then returns it.

type Daemon

type Daemon struct {
	Address string `json:"Address"` // Network address for both TCP and UDP to listen to, e.g. 0.0.0.0 for all network interfaces.
	// AllowQueryFromCidrs are the network address blocks (both IPv4 and IPv6)
	// from which clients may send recursive queries.
	// Queries that are directed at DNS server's own domain names
	// (MyDomainNames) are not restricted by this list.
	AllowQueryFromCidrs []string `json:"AllowQueryFromCidrs"`
	// PerIPLimit is the approximate number of UDP packets and TCP connections accepted from each client IP per second.
	// The limit needs to be sufficiently high for TCP-over-DNS queries.
	PerIPLimit int `json:"PerIPLimit"`
	// PerIPQueryLimit is the approximate number of DNS queries (excluding TCP-over-DNS) processed from each client IP per second.
	PerIPQueryLimit int `json:"PerIPQueryLimit"`
	// Forwarders are recursive DNS resolvers for all query types. All resolvers
	// must support both TCP and UDP.
	Forwarders []string `json:"Forwarders"`
	// Processor enables execution of toolbox commands via DNS TXT queries when
	// the queries are directed at the server's own domain name(s).
	Processor *toolbox.CommandProcessor `json:"-"`
	// MyDomainNames lists the domain names belonging to laitos server itself.
	// When laitos DNS server is used as these domains' name servers, the DNS
	// server will automaitcally respond authoritatively to SOA, NS, MX, and A
	// requests for the domains.
	// This is especially important to support TCP-over-DNS usage and DNS app
	// command runner requests.
	// CustomRecords take precedence over these automatically constructed
	// responses. For all other domain names, the DNS server works as a stub
	// forward-only resolver.
	MyDomainNames []string `json:"MyDomainNames"`
	// CustomRecords are the user-defined DNS records for which the DNS server
	// will respond authoritatively.
	CustomRecords map[string]*CustomRecord `json:"CustomRecords"`

	UDPPort int `json:"UDPPort"` // UDP port to listen on
	TCPPort int `json:"TCPPort"` // TCP port to listen on

	// TCPProxy is a TCP-over-DNS proxy server.
	TCPProxy *Proxy `json:"TCPProxy"`
	// DNSRelay provides a transport for forwarded queries.
	DNSRelay *DNSRelay `json:"-"`
	// contains filtered or unexported fields
}

A DNS forwarder daemon that selectively refuse to answer certain A record requests made against advertisement servers.

func (*Daemon) GetTCPStatsCollector

func (daemon *Daemon) GetTCPStatsCollector() *misc.Stats

GetTCPStatsCollector returns stats collector for the TCP server of this daemon.

func (*Daemon) GetUDPStatsCollector

func (daemon *Daemon) GetUDPStatsCollector() *misc.Stats

GetUDPStatsCollector returns stats collector for the UDP server of this daemon.

func (*Daemon) HandleTCPConnection

func (daemon *Daemon) HandleTCPConnection(logger *lalog.Logger, ip string, conn *net.TCPConn)

HandleTCPConnection reads a DNS query from a TCP client and responds to it with the DNS query result.

func (*Daemon) HandleUDPClient

func (daemon *Daemon) HandleUDPClient(logger *lalog.Logger, ip string, client *net.UDPAddr, packet []byte, srv *net.UDPConn)

Read a feature command from each input line, then invoke the requested feature and write the execution result back to client.

func (*Daemon) Initialise

func (daemon *Daemon) Initialise() error

Check configuration and initialise internal states.

func (*Daemon) IsInBlacklist

func (daemon *Daemon) IsInBlacklist(nameOrIP string) bool

IsInBlacklist returns true only if the input domain name or IP address is black listed. If the domain name represents a sub-domain name, then the function strips the sub-domain portion in order to check it against black list.

func (*Daemon) StartAndBlock

func (daemon *Daemon) StartAndBlock() error

You may call this function only after having called Initialise()! Start DNS daemon on configured TCP and UDP ports. Block caller until both listeners are told to stop. If either TCP or UDP port fails to listen, all listeners are closed and an error is returned.

func (*Daemon) Stop

func (daemon *Daemon) Stop()

Close all of open TCP and UDP listeners so that they will cease processing incoming connections.

func (*Daemon) UpdateBlackList

func (daemon *Daemon) UpdateBlackList(blacklistedNames []string)

UpdateBlackList downloads the latest blacklist files from PGL and MVPS, resolves the IP addresses of each domain, and stores the latest blacklist names and IP addresses into blacklist map.

type HTTPProxyServer

type HTTPProxyServer struct {
	// Address is the network address for the HTTP proxy to listen on, e.g.
	// 127.0.0.1 to serve the localhost alone.
	Address string `json:"Address"`
	// Port to listen on.
	Port int `json:"Port"`
	// Config contains the parameters for the initiator of the proxy
	// connections to configure the remote transmission control.
	Config tcpoverdns.InitiatorConfig

	// Debug enables verbose logging for IO activities.
	Debug bool
	// EnableTXTRequests forces the DNS client to transport TCP-over-DNS
	// segments in TXT queries instead of the usual CNAME queries.
	EnableTXTRequests bool
	// DownstreamSegmentLength is used for configuring the responder (remote)
	// transmission control's segment length. This enables better utilisation
	// of available bandwidth when the upstream and downstream have asymmetric
	// capacity.
	DownstreamSegmentLength int
	// RequestOTPSecret is the proxy OTP secret for laitos DNS server to
	// authorise this client's connection requests.
	RequestOTPSecret string `json:"RequestOTPSecret"`

	// DNSResolver is the address of a local or public recursive resolver
	// (ip:port).
	DNSResolver string
	// DNSHostName is the host name of the TCP-over-DNS proxy server.
	DNSHostName string
	// contains filtered or unexported fields
}

HTTPProxyServer is an HTTP proxy server that tunnels its HTTP clients' traffic through TCP-over-DNS proxy.

func (*HTTPProxyServer) Initialise

func (proxy *HTTPProxyServer) Initialise(ctx context.Context) error

Initialise validates configuration parameters and initialises the internal state of the daemon.

func (*HTTPProxyServer) ProxyHandler

func (proxy *HTTPProxyServer) ProxyHandler(w http.ResponseWriter, r *http.Request)

ProxyHandler is an HTTP handler function that uses TCP-over-DNS proxy to transport requests and responses.

func (*HTTPProxyServer) StartAndBlock

func (proxy *HTTPProxyServer) StartAndBlock() error

StartAndBlock starts a web server to serve the HTTP(S) proxy endpoint. The function will block caller until Stop is called.

func (*HTTPProxyServer) Stop

func (proxy *HTTPProxyServer) Stop()

Stop the proxy server.

type LatestCommands

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

LatestCommands records the commands executed during the past TTL-period. The DNS server tracks these command execution results to avoid repeatedly executing the same command for a recursive DNS server that uses a timeout too short.

func NewLatestCommands

func NewLatestCommands() (rec *LatestCommands)

NewLatestCommands constructs a new instance of LatestCommands and initialises its internal state.

func (*LatestCommands) Execute

func (rec *LatestCommands) Execute(ctx context.Context, cmdProcessor *toolbox.CommandProcessor, clientIP, cmdInput string) (result *toolbox.Result)

Execute looks for an ongoing or past execution of the command input. If an ongoing execution of the command is found, then the function waits until result is ready from the ongoing execution and returns it; if the same command has been executed recently, the function will return the past execution result; otherwise, the command execution begins right away.

type NSRecord

type NSRecord struct {
	Names []string `json:"Names"`
}

func (*NSRecord) Exists

func (rec *NSRecord) Exists() bool

func (NSRecord) Lint

func (ns NSRecord) Lint() error

Lint checks the record for errors, and modifies it in-place to conform to protocol requirements.

type ProxiedConnection

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

ProxiedConnection handles an individual proxy connection to transport data between local transmission control and the one on the remote DNS proxy server.

func (*ProxiedConnection) Start

func (conn *ProxiedConnection) Start() error

Start configures and then starts the transmission control on local side, and spawns a background goroutine to transport segments back and forth using DNS queries. The function returns when the local transmission control transitions to the established state, or an error.

type Proxy

type Proxy struct {
	// DNSDaemon helps the proxy to identify advertising/malware proxy
	// destinations and to refuse serving their clients.
	DNSDaemon *Daemon `json:"-"`

	// RequestOTPSecret is a TOTP secret for authorising incoming connection
	// requests.
	RequestOTPSecret string `json:"RequestOTPSecret"`
	// Debug enables verbose logging for IO activities.
	Debug bool `json:"Debug"`

	// Linger is a brief period of time for a proxy connection to stay before it
	// is removed from the internal collection of proxy connections. The delay
	// is crucial to allow the final segments of each proxy connection to be
	// received by proxy client - including the segment with ResetTerminate.
	Linger time.Duration `json:"-"`

	// DialTimeout is the timeout used for creating new a proxy TCP connection.
	DialTimeout time.Duration `json:"-"`
	// contains filtered or unexported fields
}

Proxy manages the full life cycle of multiple transmission controls created for the purpose of relaying TCP connections.

func (*Proxy) Close

func (proxy *Proxy) Close() error

Close terminates all ongoing transmission controls. The function always returns nil.

func (*Proxy) Receive

func (proxy *Proxy) Receive(in tcpoverdns.Segment) (tcpoverdns.Segment, bool)

Receive processes an incoming segment and relay the segment to an existing transmission control, or create a new transmission control for the proxy destination.

func (*Proxy) Start

func (proxy *Proxy) Start(ctx context.Context)

Start initialises the internal state of the proxy.

type ProxyConnection

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

ProxyConnection consists of a transmission control paired to a TCP connection relayed by the transmission control.

func (*ProxyConnection) Close

func (conn *ProxyConnection) Close() error

Close and terminate the proxy TCP connection and its transmission control.

func (*ProxyConnection) Start

func (conn *ProxyConnection) Start()

Start piping data back and forth between proxy TCP connection and transmission control. The function blocks until the underlying TC is closed.

func (*ProxyConnection) WaitSegment

func (conn *ProxyConnection) WaitSegment(ctx context.Context) (tcpoverdns.Segment, bool)

WaitSegment busy-waits until a new segment is available from the output segment backlog, and then pops the segment.

type ProxyRequest

type ProxyRequest struct {
	// Network name of the address (e.g. "tcp"), this takes precedence over the
	// port number when the network name is specified.
	Network string `json:"n"`
	// Port number in the absence of network name.
	Port int `json:"p"`
	// Address is the host IP address or network address (IP:port).
	Address string `json:"a"`
	// AccessTOTP is a time-based OTP that authorises the connection request.
	AccessTOTP string `json:"t"`
}

ProxyRequest is the data sent by a proxy client to initiate a connection toward a proxy destination.

type ResponseCache

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

ResponseCache caches TCP-over-DNS query responses for a brief period of time.

func NewResponseCache

func NewResponseCache(expiry time.Duration, cleanUpEvery int) *ResponseCache

NewResponseCache constructs a new instance of ResponseCache and initialises its internal state.

func (*ResponseCache) GetOrSet

func (cache *ResponseCache) GetOrSet(name string, setFun func() tcpoverdns.Segment) tcpoverdns.Segment

Get returns the cached name response, or it invokes setFun and to return and cache its response.

type TCPForwarderQuery

type TCPForwarderQuery struct {
	MyServer    *net.Conn
	QueryPacket []byte
}

A query to forward to DNS forwarder via TCP.

type TextRecord

type TextRecord struct {
	Entries []string `json:"Entries"`
}

TextRecord is a TXT record.

func (*TextRecord) Exists

func (rec *TextRecord) Exists() bool

func (*TextRecord) Lint

func (txt *TextRecord) Lint() error

Lint checks the record for errors, and modifies it in-place to conform to protocol requirements.

type UDPQuery

type UDPQuery struct {
	MyServer    *net.UDPConn
	ClientAddr  *net.UDPAddr
	QueryPacket []byte
}

A query to forward to DNS forwarder via DNS.

type V4AddressRecord

type V4AddressRecord struct {
	AddressRecord
}

V4AddressRecord is an IPv4 or CNAME address record.

func (*V4AddressRecord) Lint

func (a *V4AddressRecord) Lint() error

Lint checks the record for errors, and modifies it in-place to conform to protocol requirements.

type V6AddressRecord

type V6AddressRecord struct {
	AddressRecord
}

V46ddressRecord is an IPv6 or CNAME address record.

func (*V6AddressRecord) Lint

func (aaaa *V6AddressRecord) Lint() error

Lint checks the record for errors, and modifies it in-place to conform to protocol requirements.

Jump to

Keyboard shortcuts

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