dns.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. package main
  2. import (
  3. "bytes"
  4. "crypto/rand"
  5. "encoding/base32"
  6. "encoding/binary"
  7. "fmt"
  8. "io"
  9. "log"
  10. "net"
  11. "time"
  12. "www.bamsoftware.com/git/dnstt.git/dns"
  13. "www.bamsoftware.com/git/dnstt.git/turbotunnel"
  14. )
  15. const (
  16. // How many bytes of random padding to insert into queries.
  17. numPadding = 3
  18. // In an otherwise empty polling query, insert even more random padding,
  19. // to reduce the chance of a cache hit. Cannot be greater than 31,
  20. // because the prefix codes indicating padding start at 224.
  21. numPaddingForPoll = 8
  22. // sendLoop has a poll timer that automatically sends an empty polling
  23. // query when a certain amount of time has elapsed without a send. The
  24. // poll timer is initially set to initPollDelay. It increases by a
  25. // factor of pollDelayMultiplier every time the poll timer expires, up
  26. // to a maximum of maxPollDelay. The poll timer is reset to
  27. // initPollDelay whenever an a send occurs that is not the result of the
  28. // poll timer expiring.
  29. initPollDelay = 500 * time.Millisecond
  30. maxPollDelay = 10 * time.Second
  31. pollDelayMultiplier = 2.0
  32. // A limit on the number of empty poll requests we may send in a burst
  33. // as a result of receiving data.
  34. pollLimit = 16
  35. )
  36. // base32Encoding is a base32 encoding without padding.
  37. var base32Encoding = base32.StdEncoding.WithPadding(base32.NoPadding)
  38. // DNSPacketConn provides a packet-sending and -receiving interface over various
  39. // forms of DNS. It handles the details of how packets and padding are encoded
  40. // as a DNS name in the Question section of an upstream query, and as a TXT RR
  41. // in downstream responses.
  42. //
  43. // DNSPacketConn does not handle the mechanics of actually sending and receiving
  44. // encoded DNS messages. That is rather the responsibility of some other
  45. // net.PacketConn such as net.UDPConn, HTTPPacketConn, or TLSPacketConn, one of
  46. // which must be provided to NewDNSPacketConn.
  47. //
  48. // We don't have a need to match up a query and a response by ID. Queries and
  49. // responses are vehicles for carrying data and for our purposes don't need to
  50. // be correlated. When sending a query, we generate a random ID, and when
  51. // receiving a response, we ignore the ID.
  52. type DNSPacketConn struct {
  53. clientID turbotunnel.ClientID
  54. domain dns.Name
  55. // Sending on pollChan permits sendLoop to send an empty polling query.
  56. // sendLoop also does its own polling according to a time schedule.
  57. pollChan chan struct{}
  58. // QueuePacketConn is the direct receiver of ReadFrom and WriteTo calls.
  59. // recvLoop and sendLoop take the messages out of the receive and send
  60. // queues and actually put them on the network.
  61. *turbotunnel.QueuePacketConn
  62. }
  63. // NewDNSPacketConn creates a new DNSPacketConn. transport, through its WriteTo
  64. // and ReadFrom methods, handles the actual sending and receiving the DNS
  65. // messages encoded by DNSPacketConn. addr is the address to be passed to
  66. // transport.WriteTo whenever a message needs to be sent.
  67. func NewDNSPacketConn(transport net.PacketConn, addr net.Addr, domain dns.Name) *DNSPacketConn {
  68. // Generate a new random ClientID.
  69. clientID := turbotunnel.NewClientID()
  70. c := &DNSPacketConn{
  71. clientID: clientID,
  72. domain: domain,
  73. pollChan: make(chan struct{}, pollLimit),
  74. QueuePacketConn: turbotunnel.NewQueuePacketConn(clientID, 0),
  75. }
  76. go func() {
  77. err := c.recvLoop(transport)
  78. if err != nil {
  79. log.Printf("recvLoop: %v", err)
  80. }
  81. }()
  82. go func() {
  83. err := c.sendLoop(transport, addr)
  84. if err != nil {
  85. log.Printf("sendLoop: %v", err)
  86. }
  87. }()
  88. return c
  89. }
  90. // dnsResponsePayload extracts the downstream payload of a DNS response, encoded
  91. // into the RDATA of a TXT RR. It returns nil if the message doesn't pass format
  92. // checks, or if the name in its Question entry is not a subdomain of domain.
  93. func dnsResponsePayload(resp *dns.Message, domain dns.Name) []byte {
  94. if resp.Flags&0x8000 != 0x8000 {
  95. // QR != 1, this is not a response.
  96. return nil
  97. }
  98. if resp.Flags&0x000f != dns.RcodeNoError {
  99. return nil
  100. }
  101. if len(resp.Answer) != 1 {
  102. return nil
  103. }
  104. answer := resp.Answer[0]
  105. _, ok := answer.Name.TrimSuffix(domain)
  106. if !ok {
  107. // Not the name we are expecting.
  108. return nil
  109. }
  110. if answer.Type != dns.RRTypeTXT {
  111. // We only support TYPE == TXT.
  112. return nil
  113. }
  114. payload, err := dns.DecodeRDataTXT(answer.Data)
  115. if err != nil {
  116. return nil
  117. }
  118. return payload
  119. }
  120. // nextPacket reads the next length-prefixed packet from r. It returns a nil
  121. // error only when a complete packet was read. It returns io.EOF only when there
  122. // were 0 bytes remaining to read from r. It returns io.ErrUnexpectedEOF when
  123. // EOF occurs in the middle of an encoded packet.
  124. func nextPacket(r *bytes.Reader) ([]byte, error) {
  125. for {
  126. var n uint16
  127. err := binary.Read(r, binary.BigEndian, &n)
  128. if err != nil {
  129. // We may return a real io.EOF only here.
  130. return nil, err
  131. }
  132. p := make([]byte, n)
  133. _, err = io.ReadFull(r, p)
  134. // Here we must change io.EOF to io.ErrUnexpectedEOF.
  135. if err == io.EOF {
  136. err = io.ErrUnexpectedEOF
  137. }
  138. return p, err
  139. }
  140. }
  141. // recvLoop repeatedly calls transport.ReadFrom to receive a DNS message,
  142. // extracts its payload and breaks it into packets, and stores the packets in a
  143. // queue to be returned from a future call to c.ReadFrom.
  144. //
  145. // Whenever we receive a DNS response containing at least one data packet, we
  146. // send on c.pollChan to permit sendLoop to send an immediate polling queries.
  147. // KCP itself will also send an ACK packet for incoming data, which is
  148. // effectively a second poll. Therefore, each time we receive data, we send up
  149. // to 2 polling queries (or 1 + f polling queries, if KCP only ACKs an f
  150. // fraction of incoming data). We say "up to" because sendLoop will discard an
  151. // empty polling query if it has an organic non-empty packet to send (this goes
  152. // also for KCP's organic ACK packets).
  153. //
  154. // The intuition behind polling immediately after receiving is that if server
  155. // has just had something to send, it may have more to send, and in order for
  156. // the server to send anything, we must give it a query to respond to. The
  157. // intuition behind polling *2 times* (or 1 + f times) is similar to TCP slow
  158. // start: we want to maintain some number of queries "in flight", and the faster
  159. // the server is sending, the higher that number should be. If we polled only
  160. // once for each received packet, we would tend to have only one query in flight
  161. // at a time, ping-pong style. The first polling query replaces the in-flight
  162. // query that has just finished its duty in returning data to us; the second
  163. // grows the effective in-flight window proportional to the rate at which
  164. // data-carrying responses are being received. Compare to Eq. (2) of
  165. // https://tools.ietf.org/html/rfc5681#section-3.1. The differences are that we
  166. // count messages, not bytes, and we don't maintain an explicit window. If a
  167. // response comes back without data, or if a query or response is dropped by the
  168. // network, then we don't poll again, which decreases the effective in-flight
  169. // window.
  170. func (c *DNSPacketConn) recvLoop(transport net.PacketConn) error {
  171. for {
  172. var buf [4096]byte
  173. n, addr, err := transport.ReadFrom(buf[:])
  174. if err != nil {
  175. if err, ok := err.(net.Error); ok && err.Temporary() {
  176. log.Printf("ReadFrom temporary error: %v", err)
  177. continue
  178. }
  179. return err
  180. }
  181. // Got a response. Try to parse it as a DNS message.
  182. resp, err := dns.MessageFromWireFormat(buf[:n])
  183. if err != nil {
  184. log.Printf("MessageFromWireFormat: %v", err)
  185. continue
  186. }
  187. payload := dnsResponsePayload(&resp, c.domain)
  188. // Pull out the packets contained in the payload.
  189. r := bytes.NewReader(payload)
  190. any := false
  191. for {
  192. p, err := nextPacket(r)
  193. if err != nil {
  194. break
  195. }
  196. any = true
  197. c.QueuePacketConn.QueueIncoming(p, addr)
  198. }
  199. // If the payload contained one or more packets, permit sendLoop
  200. // to poll immediately. ACKs on received data will effectively
  201. // serve as another stream of polls whose rate is proportional
  202. // to the rate of incoming packets.
  203. if any {
  204. select {
  205. case c.pollChan <- struct{}{}:
  206. default:
  207. }
  208. }
  209. }
  210. }
  211. // chunks breaks p into non-empty subslices of at most n bytes, greedily so that
  212. // only final subslice has length < n.
  213. func chunks(p []byte, n int) [][]byte {
  214. var result [][]byte
  215. for len(p) > 0 {
  216. sz := len(p)
  217. if sz > n {
  218. sz = n
  219. }
  220. result = append(result, p[:sz])
  221. p = p[sz:]
  222. }
  223. return result
  224. }
  225. // send sends p as a single packet encoded into a DNS query, using
  226. // transport.WriteTo(query, addr). The length of p must be less than 224 bytes.
  227. //
  228. // Here is an example of how a packet is encoded into a DNS name, using
  229. // p = "supercalifragilisticexpialidocious"
  230. // c.clientID = "CLIENTID"
  231. // domain = "t.example.com"
  232. //
  233. // 0. Start with the raw packet contents.
  234. // supercalifragilisticexpialidocious
  235. // 1. Length-prefix the packet and add random padding. A length prefix L < 0xe0
  236. // means a data packet of L bytes. A length prefix L >= 0xe0 means padding of L -
  237. // 0xe0 bytes (not counting the length of the length prefix itself).
  238. // \xe3\xd9\xa3\x15\x22supercalifragilisticexpialidocious
  239. // 2. Prefix the ClientID.
  240. // CLIENTID\xe3\xd9\xa3\x15\x22supercalifragilisticexpialidocious
  241. // 3. Base32-encode, without padding and in lower case.
  242. // ingesrkokreujy6zumkse43vobsxey3bnruwm4tbm5uwy2ltoruwgzlyobuwc3djmrxwg2lpovzq
  243. // 4. Break into labels of at most 63 octets.
  244. // ingesrkokreujy6zumkse43vobsxey3bnruwm4tbm5uwy2ltoruwgzlyobuwc3d.jmrxwg2lpovzq
  245. // 5. Append the domain.
  246. // ingesrkokreujy6zumkse43vobsxey3bnruwm4tbm5uwy2ltoruwgzlyobuwc3d.jmrxwg2lpovzq.t.example.com
  247. func (c *DNSPacketConn) send(transport net.PacketConn, p []byte, addr net.Addr) error {
  248. var decoded []byte
  249. {
  250. if len(p) >= 224 {
  251. return fmt.Errorf("too long")
  252. }
  253. var buf bytes.Buffer
  254. // ClientID
  255. buf.Write(c.clientID[:])
  256. n := numPadding
  257. if len(p) == 0 {
  258. n = numPaddingForPoll
  259. }
  260. // Padding / cache inhibition
  261. buf.WriteByte(byte(224 + n))
  262. io.CopyN(&buf, rand.Reader, int64(n))
  263. // Packet contents
  264. if len(p) > 0 {
  265. buf.WriteByte(byte(len(p)))
  266. buf.Write(p)
  267. }
  268. decoded = buf.Bytes()
  269. }
  270. encoded := make([]byte, base32Encoding.EncodedLen(len(decoded)))
  271. base32Encoding.Encode(encoded, decoded)
  272. encoded = bytes.ToLower(encoded)
  273. labels := chunks(encoded, 63)
  274. labels = append(labels, c.domain...)
  275. name, err := dns.NewName(labels)
  276. if err != nil {
  277. return err
  278. }
  279. var id uint16
  280. binary.Read(rand.Reader, binary.BigEndian, &id)
  281. query := &dns.Message{
  282. ID: id,
  283. Flags: 0x0100, // QR = 0, RD = 1
  284. Question: []dns.Question{
  285. {
  286. Name: name,
  287. Type: dns.RRTypeTXT,
  288. Class: dns.ClassIN,
  289. },
  290. },
  291. // EDNS(0)
  292. Additional: []dns.RR{
  293. {
  294. Name: dns.Name{},
  295. Type: dns.RRTypeOPT,
  296. Class: 4096, // requester's UDP payload size
  297. TTL: 0, // extended RCODE and flags
  298. Data: []byte{},
  299. },
  300. },
  301. }
  302. buf, err := query.WireFormat()
  303. if err != nil {
  304. return err
  305. }
  306. _, err = transport.WriteTo(buf, addr)
  307. return err
  308. }
  309. // sendLoop takes packets that have been written using c.WriteTo, and sends them
  310. // on the network using send. It also does polling with empty packets when
  311. // requested by pollChan or after a timeout.
  312. func (c *DNSPacketConn) sendLoop(transport net.PacketConn, addr net.Addr) error {
  313. pollDelay := initPollDelay
  314. pollTimer := time.NewTimer(pollDelay)
  315. for {
  316. var p []byte
  317. outgoing := c.QueuePacketConn.OutgoingQueue(addr)
  318. pollTimerExpired := false
  319. // Prioritize sending an actual data packet from outgoing. Only
  320. // consider a poll when outgoing is empty.
  321. select {
  322. case p = <-outgoing:
  323. default:
  324. select {
  325. case p = <-outgoing:
  326. case <-c.pollChan:
  327. case <-pollTimer.C:
  328. pollTimerExpired = true
  329. }
  330. }
  331. if len(p) > 0 {
  332. // A data-carrying packet displaces one pending poll
  333. // opportunity, if any.
  334. select {
  335. case <-c.pollChan:
  336. default:
  337. }
  338. }
  339. if pollTimerExpired {
  340. // We're polling because it's been a while since we last
  341. // polled. Increase the poll delay.
  342. pollDelay = time.Duration(float64(pollDelay) * pollDelayMultiplier)
  343. if pollDelay > maxPollDelay {
  344. pollDelay = maxPollDelay
  345. }
  346. } else {
  347. // We're sending an actual data packet, or we're polling
  348. // in response to a received packet. Reset the poll
  349. // delay to initial.
  350. if !pollTimer.Stop() {
  351. <-pollTimer.C
  352. }
  353. pollDelay = initPollDelay
  354. }
  355. pollTimer.Reset(pollDelay)
  356. // Unlike in the server, in the client we assume that because
  357. // the data capacity of queries is so limited, it's not worth
  358. // trying to send more than one packet per query.
  359. err := c.send(transport, p, addr)
  360. if err != nil {
  361. log.Printf("send: %v", err)
  362. continue
  363. }
  364. }
  365. }