client.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534
  1. package dns
  2. // A client implementation.
  3. import (
  4. "bytes"
  5. "context"
  6. "crypto/tls"
  7. "encoding/binary"
  8. "io"
  9. "net"
  10. "time"
  11. )
  12. const dnsTimeout time.Duration = 2 * time.Second
  13. const tcpIdleTimeout time.Duration = 8 * time.Second
  14. // A Conn represents a connection to a DNS server.
  15. type Conn struct {
  16. net.Conn // a net.Conn holding the connection
  17. UDPSize uint16 // minimum receive buffer for UDP messages
  18. TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be fully qualified
  19. rtt time.Duration
  20. t time.Time
  21. tsigRequestMAC string
  22. }
  23. // A Client defines parameters for a DNS client.
  24. type Client struct {
  25. Net string // if "tcp" or "tcp-tls" (DNS over TLS) a TCP query will be initiated, otherwise an UDP one (default is "" for UDP)
  26. UDPSize uint16 // minimum receive buffer for UDP messages
  27. TLSConfig *tls.Config // TLS connection configuration
  28. Timeout time.Duration // a cumulative timeout for dial, write and read, defaults to 0 (disabled) - overrides DialTimeout, ReadTimeout and WriteTimeout when non-zero
  29. DialTimeout time.Duration // net.DialTimeout, defaults to 2 seconds - overridden by Timeout when that value is non-zero
  30. ReadTimeout time.Duration // net.Conn.SetReadTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero
  31. WriteTimeout time.Duration // net.Conn.SetWriteTimeout value for connections, defaults to 2 seconds - overridden by Timeout when that value is non-zero
  32. TsigSecret map[string]string // secret(s) for Tsig map[<zonename>]<base64 secret>, zonename must be fully qualified
  33. SingleInflight bool // if true suppress multiple outstanding queries for the same Qname, Qtype and Qclass
  34. group singleflight
  35. }
  36. // Exchange performs a synchronous UDP query. It sends the message m to the address
  37. // contained in a and waits for a reply. Exchange does not retry a failed query, nor
  38. // will it fall back to TCP in case of truncation.
  39. // See client.Exchange for more information on setting larger buffer sizes.
  40. func Exchange(m *Msg, a string) (r *Msg, err error) {
  41. var co *Conn
  42. co, err = DialTimeout("udp", a, dnsTimeout)
  43. if err != nil {
  44. return nil, err
  45. }
  46. defer co.Close()
  47. opt := m.IsEdns0()
  48. // If EDNS0 is used use that for size.
  49. if opt != nil && opt.UDPSize() >= MinMsgSize {
  50. co.UDPSize = opt.UDPSize()
  51. }
  52. co.SetWriteDeadline(time.Now().Add(dnsTimeout))
  53. if err = co.WriteMsg(m); err != nil {
  54. return nil, err
  55. }
  56. co.SetReadDeadline(time.Now().Add(dnsTimeout))
  57. r, err = co.ReadMsg()
  58. if err == nil && r.Id != m.Id {
  59. err = ErrId
  60. }
  61. return r, err
  62. }
  63. // ExchangeContext performs a synchronous UDP query, like Exchange. It
  64. // additionally obeys deadlines from the passed Context.
  65. func ExchangeContext(ctx context.Context, m *Msg, a string) (r *Msg, err error) {
  66. // Combine context deadline with built-in timeout. Context chooses whichever
  67. // is sooner.
  68. timeoutCtx, cancel := context.WithTimeout(ctx, dnsTimeout)
  69. defer cancel()
  70. deadline, _ := timeoutCtx.Deadline()
  71. co := new(Conn)
  72. dialer := net.Dialer{}
  73. co.Conn, err = dialer.DialContext(timeoutCtx, "udp", a)
  74. if err != nil {
  75. return nil, err
  76. }
  77. defer co.Conn.Close()
  78. opt := m.IsEdns0()
  79. // If EDNS0 is used use that for size.
  80. if opt != nil && opt.UDPSize() >= MinMsgSize {
  81. co.UDPSize = opt.UDPSize()
  82. }
  83. co.SetWriteDeadline(deadline)
  84. if err = co.WriteMsg(m); err != nil {
  85. return nil, err
  86. }
  87. co.SetReadDeadline(deadline)
  88. r, err = co.ReadMsg()
  89. if err == nil && r.Id != m.Id {
  90. err = ErrId
  91. }
  92. return r, err
  93. }
  94. // ExchangeConn performs a synchronous query. It sends the message m via the connection
  95. // c and waits for a reply. The connection c is not closed by ExchangeConn.
  96. // This function is going away, but can easily be mimicked:
  97. //
  98. // co := &dns.Conn{Conn: c} // c is your net.Conn
  99. // co.WriteMsg(m)
  100. // in, _ := co.ReadMsg()
  101. // co.Close()
  102. //
  103. func ExchangeConn(c net.Conn, m *Msg) (r *Msg, err error) {
  104. println("dns: this function is deprecated")
  105. co := new(Conn)
  106. co.Conn = c
  107. if err = co.WriteMsg(m); err != nil {
  108. return nil, err
  109. }
  110. r, err = co.ReadMsg()
  111. if err == nil && r.Id != m.Id {
  112. err = ErrId
  113. }
  114. return r, err
  115. }
  116. // Exchange performs a synchronous query. It sends the message m to the address
  117. // contained in a and waits for a reply. Basic use pattern with a *dns.Client:
  118. //
  119. // c := new(dns.Client)
  120. // in, rtt, err := c.Exchange(message, "127.0.0.1:53")
  121. //
  122. // Exchange does not retry a failed query, nor will it fall back to TCP in
  123. // case of truncation.
  124. // It is up to the caller to create a message that allows for larger responses to be
  125. // returned. Specifically this means adding an EDNS0 OPT RR that will advertise a larger
  126. // buffer, see SetEdns0. Messages without an OPT RR will fallback to the historic limit
  127. // of 512 bytes.
  128. func (c *Client) Exchange(m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
  129. return c.ExchangeContext(context.Background(), m, a)
  130. }
  131. // ExchangeContext acts like Exchange, but honors the deadline on the provided
  132. // context, if present. If there is both a context deadline and a configured
  133. // timeout on the client, the earliest of the two takes effect.
  134. func (c *Client) ExchangeContext(ctx context.Context, m *Msg, a string) (
  135. r *Msg,
  136. rtt time.Duration,
  137. err error) {
  138. if !c.SingleInflight {
  139. return c.exchange(ctx, m, a)
  140. }
  141. // This adds a bunch of garbage, TODO(miek).
  142. t := "nop"
  143. if t1, ok := TypeToString[m.Question[0].Qtype]; ok {
  144. t = t1
  145. }
  146. cl := "nop"
  147. if cl1, ok := ClassToString[m.Question[0].Qclass]; ok {
  148. cl = cl1
  149. }
  150. r, rtt, err, shared := c.group.Do(m.Question[0].Name+t+cl, func() (*Msg, time.Duration, error) {
  151. return c.exchange(ctx, m, a)
  152. })
  153. if r != nil && shared {
  154. r = r.Copy()
  155. }
  156. if err != nil {
  157. return r, rtt, err
  158. }
  159. return r, rtt, nil
  160. }
  161. func (c *Client) dialTimeout() time.Duration {
  162. if c.Timeout != 0 {
  163. return c.Timeout
  164. }
  165. if c.DialTimeout != 0 {
  166. return c.DialTimeout
  167. }
  168. return dnsTimeout
  169. }
  170. func (c *Client) readTimeout() time.Duration {
  171. if c.ReadTimeout != 0 {
  172. return c.ReadTimeout
  173. }
  174. return dnsTimeout
  175. }
  176. func (c *Client) writeTimeout() time.Duration {
  177. if c.WriteTimeout != 0 {
  178. return c.WriteTimeout
  179. }
  180. return dnsTimeout
  181. }
  182. func (c *Client) exchange(ctx context.Context, m *Msg, a string) (r *Msg, rtt time.Duration, err error) {
  183. var co *Conn
  184. network := "udp"
  185. tls := false
  186. switch c.Net {
  187. case "tcp-tls":
  188. network = "tcp"
  189. tls = true
  190. case "tcp4-tls":
  191. network = "tcp4"
  192. tls = true
  193. case "tcp6-tls":
  194. network = "tcp6"
  195. tls = true
  196. default:
  197. if c.Net != "" {
  198. network = c.Net
  199. }
  200. }
  201. var deadline time.Time
  202. if c.Timeout != 0 {
  203. deadline = time.Now().Add(c.Timeout)
  204. }
  205. dialDeadline := deadlineOrTimeoutOrCtx(ctx, deadline, c.dialTimeout())
  206. dialTimeout := dialDeadline.Sub(time.Now())
  207. if tls {
  208. co, err = DialTimeoutWithTLS(network, a, c.TLSConfig, dialTimeout)
  209. } else {
  210. co, err = DialTimeout(network, a, dialTimeout)
  211. }
  212. if err != nil {
  213. return nil, 0, err
  214. }
  215. defer co.Close()
  216. opt := m.IsEdns0()
  217. // If EDNS0 is used use that for size.
  218. if opt != nil && opt.UDPSize() >= MinMsgSize {
  219. co.UDPSize = opt.UDPSize()
  220. }
  221. // Otherwise use the client's configured UDP size.
  222. if opt == nil && c.UDPSize >= MinMsgSize {
  223. co.UDPSize = c.UDPSize
  224. }
  225. co.TsigSecret = c.TsigSecret
  226. co.SetWriteDeadline(deadlineOrTimeoutOrCtx(ctx, deadline, c.writeTimeout()))
  227. if err = co.WriteMsg(m); err != nil {
  228. return nil, 0, err
  229. }
  230. co.SetReadDeadline(deadlineOrTimeoutOrCtx(ctx, deadline, c.readTimeout()))
  231. r, err = co.ReadMsg()
  232. if err == nil && r.Id != m.Id {
  233. err = ErrId
  234. }
  235. return r, co.rtt, err
  236. }
  237. // ReadMsg reads a message from the connection co.
  238. // If the received message contains a TSIG record the transaction
  239. // signature is verified.
  240. func (co *Conn) ReadMsg() (*Msg, error) {
  241. p, err := co.ReadMsgHeader(nil)
  242. if err != nil {
  243. return nil, err
  244. }
  245. m := new(Msg)
  246. if err := m.Unpack(p); err != nil {
  247. // If ErrTruncated was returned, we still want to allow the user to use
  248. // the message, but naively they can just check err if they don't want
  249. // to use a truncated message
  250. if err == ErrTruncated {
  251. return m, err
  252. }
  253. return nil, err
  254. }
  255. if t := m.IsTsig(); t != nil {
  256. if _, ok := co.TsigSecret[t.Hdr.Name]; !ok {
  257. return m, ErrSecret
  258. }
  259. // Need to work on the original message p, as that was used to calculate the tsig.
  260. err = TsigVerify(p, co.TsigSecret[t.Hdr.Name], co.tsigRequestMAC, false)
  261. }
  262. return m, err
  263. }
  264. // ReadMsgHeader reads a DNS message, parses and populates hdr (when hdr is not nil).
  265. // Returns message as a byte slice to be parsed with Msg.Unpack later on.
  266. // Note that error handling on the message body is not possible as only the header is parsed.
  267. func (co *Conn) ReadMsgHeader(hdr *Header) ([]byte, error) {
  268. var (
  269. p []byte
  270. n int
  271. err error
  272. )
  273. // [Psiphon]
  274. // Any net.Conn but *net.UDPConn uses DNS-over-TCP protocol
  275. if _, ok := co.Conn.(*net.UDPConn); !ok {
  276. r := co.Conn.(io.Reader)
  277. // First two bytes specify the length of the entire message.
  278. l, err := tcpMsgLen(r)
  279. if err != nil {
  280. return nil, err
  281. }
  282. p = make([]byte, l)
  283. n, err = tcpRead(r, p)
  284. co.rtt = time.Since(co.t)
  285. } else {
  286. if co.UDPSize > MinMsgSize {
  287. p = make([]byte, co.UDPSize)
  288. } else {
  289. p = make([]byte, MinMsgSize)
  290. }
  291. n, err = co.Read(p)
  292. co.rtt = time.Since(co.t)
  293. }
  294. if err != nil {
  295. return nil, err
  296. } else if n < headerSize {
  297. return nil, ErrShortRead
  298. }
  299. p = p[:n]
  300. if hdr != nil {
  301. dh, _, err := unpackMsgHdr(p, 0)
  302. if err != nil {
  303. return nil, err
  304. }
  305. *hdr = dh
  306. }
  307. return p, err
  308. }
  309. // tcpMsgLen is a helper func to read first two bytes of stream as uint16 packet length.
  310. func tcpMsgLen(t io.Reader) (int, error) {
  311. p := []byte{0, 0}
  312. n, err := t.Read(p)
  313. if err != nil {
  314. return 0, err
  315. }
  316. // As seen with my local router/switch, retursn 1 byte on the above read,
  317. // resulting a a ShortRead. Just write it out (instead of loop) and read the
  318. // other byte.
  319. if n == 1 {
  320. n1, err := t.Read(p[1:])
  321. if err != nil {
  322. return 0, err
  323. }
  324. n += n1
  325. }
  326. if n != 2 {
  327. return 0, ErrShortRead
  328. }
  329. l := binary.BigEndian.Uint16(p)
  330. if l == 0 {
  331. return 0, ErrShortRead
  332. }
  333. return int(l), nil
  334. }
  335. // tcpRead calls TCPConn.Read enough times to fill allocated buffer.
  336. func tcpRead(t io.Reader, p []byte) (int, error) {
  337. n, err := t.Read(p)
  338. if err != nil {
  339. return n, err
  340. }
  341. for n < len(p) {
  342. j, err := t.Read(p[n:])
  343. if err != nil {
  344. return n, err
  345. }
  346. n += j
  347. }
  348. return n, err
  349. }
  350. // Read implements the net.Conn read method.
  351. func (co *Conn) Read(p []byte) (n int, err error) {
  352. if co.Conn == nil {
  353. return 0, ErrConnEmpty
  354. }
  355. if len(p) < 2 {
  356. return 0, io.ErrShortBuffer
  357. }
  358. // [Psiphon]
  359. // Any net.Conn but *net.UDPConn uses DNS-over-TCP protocol
  360. if _, ok := co.Conn.(*net.UDPConn); !ok {
  361. r := co.Conn.(io.Reader)
  362. l, err := tcpMsgLen(r)
  363. if err != nil {
  364. return 0, err
  365. }
  366. if l > len(p) {
  367. return int(l), io.ErrShortBuffer
  368. }
  369. return tcpRead(r, p[:l])
  370. }
  371. // UDP connection
  372. n, err = co.Conn.Read(p)
  373. if err != nil {
  374. return n, err
  375. }
  376. return n, err
  377. }
  378. // WriteMsg sends a message through the connection co.
  379. // If the message m contains a TSIG record the transaction
  380. // signature is calculated.
  381. func (co *Conn) WriteMsg(m *Msg) (err error) {
  382. var out []byte
  383. if t := m.IsTsig(); t != nil {
  384. mac := ""
  385. if _, ok := co.TsigSecret[t.Hdr.Name]; !ok {
  386. return ErrSecret
  387. }
  388. out, mac, err = TsigGenerate(m, co.TsigSecret[t.Hdr.Name], co.tsigRequestMAC, false)
  389. // Set for the next read, although only used in zone transfers
  390. co.tsigRequestMAC = mac
  391. } else {
  392. out, err = m.Pack()
  393. }
  394. if err != nil {
  395. return err
  396. }
  397. co.t = time.Now()
  398. if _, err = co.Write(out); err != nil {
  399. return err
  400. }
  401. return nil
  402. }
  403. // Write implements the net.Conn Write method.
  404. func (co *Conn) Write(p []byte) (n int, err error) {
  405. // [Psiphon]
  406. // Any net.Conn but *net.UDPConn uses DNS-over-TCP protocol
  407. if _, ok := co.Conn.(*net.UDPConn); !ok {
  408. w := co.Conn.(io.Writer)
  409. lp := len(p)
  410. if lp < 2 {
  411. return 0, io.ErrShortBuffer
  412. }
  413. if lp > MaxMsgSize {
  414. return 0, &Error{err: "message too large"}
  415. }
  416. l := make([]byte, 2, lp+2)
  417. binary.BigEndian.PutUint16(l, uint16(lp))
  418. p = append(l, p...)
  419. n, err := io.Copy(w, bytes.NewReader(p))
  420. return int(n), err
  421. }
  422. n, err = co.Conn.Write(p)
  423. return n, err
  424. }
  425. // Dial connects to the address on the named network.
  426. func Dial(network, address string) (conn *Conn, err error) {
  427. conn = new(Conn)
  428. conn.Conn, err = net.Dial(network, address)
  429. if err != nil {
  430. return nil, err
  431. }
  432. return conn, nil
  433. }
  434. // DialTimeout acts like Dial but takes a timeout.
  435. func DialTimeout(network, address string, timeout time.Duration) (conn *Conn, err error) {
  436. conn = new(Conn)
  437. conn.Conn, err = net.DialTimeout(network, address, timeout)
  438. if err != nil {
  439. return nil, err
  440. }
  441. return conn, nil
  442. }
  443. // DialWithTLS connects to the address on the named network with TLS.
  444. func DialWithTLS(network, address string, tlsConfig *tls.Config) (conn *Conn, err error) {
  445. conn = new(Conn)
  446. conn.Conn, err = tls.Dial(network, address, tlsConfig)
  447. if err != nil {
  448. return nil, err
  449. }
  450. return conn, nil
  451. }
  452. // DialTimeoutWithTLS acts like DialWithTLS but takes a timeout.
  453. func DialTimeoutWithTLS(network, address string, tlsConfig *tls.Config, timeout time.Duration) (conn *Conn, err error) {
  454. var dialer net.Dialer
  455. dialer.Timeout = timeout
  456. conn = new(Conn)
  457. conn.Conn, err = tls.DialWithDialer(&dialer, network, address, tlsConfig)
  458. if err != nil {
  459. return nil, err
  460. }
  461. return conn, nil
  462. }
  463. // deadlineOrTimeout chooses between the provided deadline and timeout
  464. // by always preferring the deadline so long as it's non-zero (regardless
  465. // of which is bigger), and returns the equivalent deadline value.
  466. func deadlineOrTimeout(deadline time.Time, timeout time.Duration) time.Time {
  467. if deadline.IsZero() {
  468. return time.Now().Add(timeout)
  469. }
  470. return deadline
  471. }
  472. // deadlineOrTimeoutOrCtx returns the earliest of: a context deadline, or the
  473. // output of deadlineOrtimeout.
  474. func deadlineOrTimeoutOrCtx(ctx context.Context, deadline time.Time, timeout time.Duration) time.Time {
  475. result := deadlineOrTimeout(deadline, timeout)
  476. if ctxDeadline, ok := ctx.Deadline(); ok && ctxDeadline.Before(result) {
  477. result = ctxDeadline
  478. }
  479. return result
  480. }