Documentation ¶
Index ¶
- Constants
- Variables
- func BuildBlackHoleAddrResponse(header dnsmessage.Header, question dnsmessage.Question) ([]byte, error)
- func BuildIPv4AddrResponse(header dnsmessage.Header, question dnsmessage.Question, record V4AddressRecord) ([]byte, error)
- func BuildIPv6AddrResponse(header dnsmessage.Header, question dnsmessage.Question, record V6AddressRecord) ([]byte, error)
- func BuildMXResponse(header dnsmessage.Header, question dnsmessage.Question, records []*net.MX) ([]byte, error)
- func BuildNSResponse(header dnsmessage.Header, question dnsmessage.Question, domainName string, ...) ([]byte, error)
- func BuildSOAResponse(header dnsmessage.Header, question dnsmessage.Question, mName, rName string) ([]byte, error)
- func BuildTCPOverDNSSegmentResponse(header dnsmessage.Header, question dnsmessage.Question, domainName string, ...) ([]byte, error)
- func BuildTextResponse(name string, header dnsmessage.Header, question dnsmessage.Question, ...) ([]byte, error)
- func CountNameLabels(in string) int
- func DecodeDTMFCommandInput(labels []string) (decodedCommand string)
- func DownloadAllBlacklists(maxEntries int, logger *lalog.Logger) []string
- func ExtractNamesFromHostsContent(content string) []string
- func MaxDownstreamSegmentLengthTXT(dnsHostName string) int
- func MaxUpstreamSegmentLength(dnsHostName string) int
- func TestServer(dnsd *Daemon, t testingstub.T)
- type AddressRecord
- type CacheEntry
- type CustomRecord
- type DNSRelay
- type Daemon
- func (daemon *Daemon) GetTCPStatsCollector() *misc.Stats
- func (daemon *Daemon) GetUDPStatsCollector() *misc.Stats
- func (daemon *Daemon) HandleTCPConnection(logger *lalog.Logger, ip string, conn *net.TCPConn)
- func (daemon *Daemon) HandleUDPClient(logger *lalog.Logger, ip string, client *net.UDPAddr, packet []byte, ...)
- func (daemon *Daemon) Initialise() error
- func (daemon *Daemon) IsInBlacklist(nameOrIP string) bool
- func (daemon *Daemon) StartAndBlock() error
- func (daemon *Daemon) Stop()
- func (daemon *Daemon) UpdateBlackList(blacklistedNames []string)
- type HTTPProxyServer
- type LatestCommands
- type NSRecord
- type ProxiedConnection
- type Proxy
- type ProxyConnection
- type ProxyRequest
- type ResponseCache
- type TCPForwarderQuery
- type TextRecord
- type UDPQuery
- type V4AddressRecord
- type V6AddressRecord
Constants ¶
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' )
const (
// EDNSBufferSize is the maximum DNS buffer size advertised to DNS clients.
EDNSBufferSize = 1232
)
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
)
const ( // MaxProxyConnectionLifetime is the maximum lifetime of a transmission // control. The transmission controls are unconditionally closed after this // duration. MaxProxyConnectionLifetime = 30 * time.Minute )
Variables ¶
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", } )
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.
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 ¶
CountNameLabels returns the number of labels in the DNS name.
func DecodeDTMFCommandInput ¶
DecodeDTMFCommandInput extracts an app command (that may contain DTMF sequences) from the input DNS query labels which exclude the domain name.
func DownloadAllBlacklists ¶
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 ¶
ExtractNamesFromHostsContent extracts domain names from hosts file content. It will not return empty lines, comments, and potentially illegal domain names.
func MaxDownstreamSegmentLengthTXT ¶
MaxDownstreamSegmentLengthTXT returns the maximum segment length appropriate for the downstream traffic direction for the DNS host name.
func MaxUpstreamSegmentLength ¶
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 ¶
Initialise validates configuration parameters and initialises the internal state of the relay.
func (*DNSRelay) StartAndBlock ¶
StartAndBlock starts the internal transmission control to act as a relay toward the DNS forwarder.
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 ¶
GetTCPStatsCollector returns stats collector for the TCP server of this daemon.
func (*Daemon) GetUDPStatsCollector ¶
GetUDPStatsCollector returns stats collector for the UDP server of this daemon.
func (*Daemon) HandleTCPConnection ¶
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 ¶
Check configuration and initialise internal states.
func (*Daemon) IsInBlacklist ¶
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 ¶
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 ¶
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.
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 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 ¶
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.
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 ¶
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 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.