dns

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Mar 10, 2025 License: GPL-3.0 Imports: 15 Imported by: 0

Documentation

Index

Constants

View Source
const (
	QTypeA    uint16 = 1  //ipv4
	QTypeAAAA uint16 = 28 ///ipv6
)

Query types.

View Source
const ClassINET uint16 = 1

ClassINET .

View Source
const HeaderLen = 12

HeaderLen is the length of dns msg header.

View Source
const UDPMaxLen = 1232

UDPMaxLen is the max size of udp dns request. https://www.dnsflagday.net/2020/

Variables

This section is empty.

Functions

func MarshalDomainTo

func MarshalDomainTo(w io.Writer, domain string) (n int, err error)

MarshalDomainTo marshals domain string struct to []byte and write to w.

func UnmarshalHeader

func UnmarshalHeader(b []byte, h *Header) error

UnmarshalHeader unmarshals []bytes to Header.

Types

type AnswerHandler

type AnswerHandler func(domain string, ip netip.Addr) error

AnswerHandler function handles the dns TypeA or TypeAAAA answer.

type Client

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

Client is a dns client struct.

func NewClient

func NewClient(proxy proxy.Proxy, config *Config) (*Client, error)

NewClient returns a new dns client.

func (*Client) AddHandler

func (c *Client) AddHandler(h AnswerHandler)

AddHandler adds a custom handler to handle the resolved result (A and AAAA).

func (*Client) AddRecord

func (c *Client) AddRecord(record string) error

AddRecord adds custom record to dns cache, format: www.example.com/1.2.3.4 or www.example.com/2606:2800:220:1:248:1893:25c8:1946

func (*Client) Exchange

func (c *Client) Exchange(reqBytes []byte, clientAddr string, preferTCP bool) ([]byte, error)

Exchange handles request message and returns response message. TODO: optimize it

func (*Client) SetServers

func (c *Client) SetServers(domain string, servers []string)

SetServers sets upstream dns servers for the given domain.

func (*Client) UpStream

func (c *Client) UpStream(domain string) *UPStream

UpStream returns upstream dns server for the given domain.

type Config

type Config struct {
	Servers   []string
	Timeout   int
	MaxTTL    int
	MinTTL    int
	Records   []string
	AlwaysTCP bool
	CacheSize int
	CacheLog  bool
	NoAAAA    bool
}

Config for dns.

type Header struct {
	ID      uint16
	Bits    uint16
	QDCOUNT uint16
	ANCOUNT uint16
	NSCOUNT uint16
	ARCOUNT uint16
}

Header format: https://www.rfc-editor.org/rfc/rfc1035#section-4.1.1 The header contains the following fields:

                                1  1  1  1  1  1
  0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                      ID                       |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|QR|   Opcode  |AA|TC|RD|RA|   Z    |   RCODE   |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                    QDCOUNT                    |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                    ANCOUNT                    |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                    NSCOUNT                    |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                    ARCOUNT                    |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

func (*Header) MarshalTo

func (h *Header) MarshalTo(w io.Writer) (int, error)

MarshalTo marshals header struct to []byte and write to w.

func (*Header) SetAncount

func (h *Header) SetAncount(ancount int)

SetAncount sets answers count.

func (*Header) SetMsgType

func (h *Header) SetMsgType(qr MsgType)

SetMsgType sets the message type.

func (*Header) SetQdcount

func (h *Header) SetQdcount(qdcount int)

SetQdcount sets query count, most dns servers only support 1 query per request.

func (*Header) SetTC

func (h *Header) SetTC(tc int)

SetTC sets the tc flag.

type LruCache

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

LruCache is the struct of LruCache.

func NewLruCache

func NewLruCache(size int) *LruCache

NewLruCache returns a new LruCache.

func (*LruCache) Get

func (c *LruCache) Get(k string) (v []byte, expired bool)

Get gets an item from cache.

func (*LruCache) Set

func (c *LruCache) Set(k string, v []byte, ttl int)

Set sets an item with key, value, and ttl(seconds). if the ttl is zero, this item will be set and never be deleted. if the key exists, update it with value and exp and move it to head. if the key does not exist, put a new item to the cache's head. finally, remove the tail if the cache is full.

type Message

type Message struct {
	Header
	// most dns implementation only support 1 question
	Question   *Question
	Answers    []*RR
	Authority  []*RR
	Additional []*RR
	// contains filtered or unexported fields
}

Message format: https://www.rfc-editor.org/rfc/rfc1035#section-4.1 All communications inside of the domain protocol are carried in a single format called a message. The top level format of message is divided into 5 sections (some of which are empty in certain cases) shown below:

+---------------------+
|        Header       |
+---------------------+
|       Question      | the question for the name server
+---------------------+
|        Answer       | RRs answering the question
+---------------------+
|      Authority      | RRs pointing toward an authority
+---------------------+
|      Additional     | RRs holding additional information

func MakeResponse

func MakeResponse(domain, ip string, ttl uint32) (*Message, error)

MakeResponse makes a dns response message for the given domain and ip address. Note: you should make sure ttl > 0.

func NewMessage

func NewMessage(id uint16, msgType MsgType) *Message

NewMessage returns a new message.

func UnmarshalMessage

func UnmarshalMessage(b []byte) (*Message, error)

UnmarshalMessage unmarshals []bytes to Message.

func (*Message) AddAnswer

func (m *Message) AddAnswer(rr *RR) error

AddAnswer adds an answer to dns message.

func (*Message) Marshal

func (m *Message) Marshal() ([]byte, error)

Marshal marshals message struct to []byte.

func (*Message) MarshalTo

func (m *Message) MarshalTo(w io.Writer) (n int, err error)

MarshalTo marshals message struct to []byte and write to w.

func (*Message) SetQuestion

func (m *Message) SetQuestion(q *Question) error

SetQuestion sets a question to dns message.

func (*Message) UnmarshalDomainPointTo

func (m *Message) UnmarshalDomainPointTo(sb *strings.Builder, offset int) error

UnmarshalDomainPointTo gets domain from offset point to string builder.

func (*Message) UnmarshalDomainTo

func (m *Message) UnmarshalDomainTo(sb *strings.Builder, b []byte) (int, error)

UnmarshalDomainTo gets domain from bytes to string builder.

func (*Message) UnmarshalQuestion

func (m *Message) UnmarshalQuestion(b []byte, q *Question) (n int, err error)

UnmarshalQuestion unmarshals []bytes to Question.

func (*Message) UnmarshalRR

func (m *Message) UnmarshalRR(start int, rr *RR) (n int, err error)

UnmarshalRR unmarshals []bytes to RR.

type MsgType

type MsgType byte

MsgType is the dns Message type.

const (
	QueryMsg    MsgType = 0
	ResponseMsg MsgType = 1
)

Message types.

type Question

type Question struct {
	QNAME  string
	QTYPE  uint16
	QCLASS uint16
}

Question format: https://www.rfc-editor.org/rfc/rfc1035#section-4.1.2 The question section is used to carry the "question" in most queries, i.e., the parameters that define what is being asked. The section contains QDCOUNT (usually 1) entries, each of the following format:

                                1  1  1  1  1  1
  0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                                               |
/                     QNAME                     /
/                                               /
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                     QTYPE                     |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                     QCLASS                    |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

func NewQuestion

func NewQuestion(qtype uint16, domain string) *Question

NewQuestion returns a new dns question.

func (*Question) MarshalTo

func (q *Question) MarshalTo(w io.Writer) (n int, err error)

MarshalTo marshals Question struct to []byte and write to w.

type RR

type RR struct {
	NAME     string
	TYPE     uint16
	CLASS    uint16
	TTL      uint32
	RDLENGTH uint16
	RDATA    []byte

	IP netip.Addr
}

RR format: https://www.rfc-editor.org/rfc/rfc1035#section-3.2.1 https://www.rfc-editor.org/rfc/rfc1035#section-4.1.3 The answer, authority, and additional sections all share the same format: a variable number of resource records, where the number of records is specified in the corresponding count field in the header. Each resource record has the following format:

                                1  1  1  1  1  1
  0  1  2  3  4  5  6  7  8  9  0  1  2  3  4  5
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                                               |
/                                               /
/                      NAME                     /
|                                               |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                      TYPE                     |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                     CLASS                     |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                      TTL                      |
|                                               |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|                   RDLENGTH                    |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
/                     RDATA                     /
/                                               /
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

func NewRR

func NewRR() *RR

NewRR returns a new dns rr.

func (*RR) MarshalTo

func (rr *RR) MarshalTo(w io.Writer) (n int, err error)

MarshalTo marshals RR struct to []byte and write to w.

type Server

type Server struct {

	// Client is used to communicate with upstream dns servers
	*Client
	// contains filtered or unexported fields
}

Server is a dns server struct.

func NewServer

func NewServer(addr string, p proxy.Proxy, config *Config) (*Server, error)

NewServer returns a new dns server.

func (*Server) ListenAndServeTCP

func (s *Server) ListenAndServeTCP(wg *sync.WaitGroup)

ListenAndServeTCP listen and serves on tcp port.

func (*Server) ListenAndServeUDP

func (s *Server) ListenAndServeUDP(wg *sync.WaitGroup)

ListenAndServeUDP listen and serves on udp port.

func (*Server) ServePacket

func (s *Server) ServePacket(pc net.PacketConn, caddr net.Addr, reqBytes []byte)

ServePacket serves dns packet conn.

func (*Server) ServeTCP

func (s *Server) ServeTCP(c net.Conn)

ServeTCP serves a dns tcp connection.

func (*Server) Start

func (s *Server) Start()

Start starts the dns forwarding server. We use WaitGroup here to ensure both udp and tcp serer are completly running, so we can start any other services later, since they may rely on dns service.

type UPStream

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

UPStream is a dns upstream.

func NewUPStream

func NewUPStream(servers []string) *UPStream

NewUPStream returns a new UpStream.

func (*UPStream) Len

func (u *UPStream) Len() int

Len returns the number of dns servers.

func (*UPStream) Server

func (u *UPStream) Server() string

Server returns a dns server.

func (*UPStream) Switch

func (u *UPStream) Switch() string

Switch switches to the next dns server.

func (*UPStream) SwitchIf

func (u *UPStream) SwitchIf(server string) string

SwitchIf switches to the next dns server if needed.

Jump to

Keyboard shortcuts

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