Projects STRLCPY dnstt Commits f96fe00a
🤬
Revision indexing in progress... (symbol navigation in revisions will be accurate after indexed)
  • ■ ■ ■ ■ ■ ■
    CHANGELOG
     1 +## v0.20210424.0
     2 + 
     3 +dnstt was part of a software security audit done by Cure53. The report
     4 +found issues of severity levels Low–Medium in dnstt and in one of its
     5 +dependencies, a package used for Noise cryptography. This release fixes
     6 +the following issues:
     7 + * UCB-02-002: Memory leak in acceptStreams() routine of dnstt server (Low)
     8 + * UCB-02-003: Potential nonce overflow in Noise protocol (Medium)
     9 + * UCB-02-004: Deprecated DH25519 Golang API used by Noise (Low)
     10 + * UCB-02-006: DoS due to unconditional nonce increment (Low)
     11 + * UCB-02-007: DoS due to missing socket timeouts (Low)
     12 +Unaddressed in this release are:
     13 + * UCB-02-005: Client ID security considerations & Noise authenticated data (Low)
     14 + * UCB-02-008: Lack of rate limiting in Snowflake and dnstt (Info)
     15 +Two other issues in the report, UCB-02-001 and UCB-02-009, do not have
     16 +to do with dnstt. For more details and the text of the report, see
     17 +https://www.bamsoftware.com/software/dnstt/security.html#cure53-turbotunnel-2021
     18 + 
     19 +Added man pages for dnstt-client and dnstt-server.
     20 + 
     21 + 
     22 +## v0.20200506.0
     23 + 
     24 +Documentation updates.
     25 + 
     26 + 
    1 27  ## v0.20200504.0
    2 28   
    3 29  Documentation updates and link to web page.
    skipped 33 lines
  • ■ ■ ■ ■
    README
    skipped 196 lines
    197 197  ```
    198 198  tunnel-client$ ./dnstt-client -doh https://doh.example/dns-query -pubkey-file server.pub t.example.com 127.0.0.1:2222
    199 199  tunnel-client$ ssh -v -N -D 127.0.0.1:7000 -o HostKeyAlias=tunnel-server -p 2222 127.0.0.1
    200  -tunnel-client$ curl --proxy http://127.0.0.1:7000/ https://wtfismyip.com/text
     200 +tunnel-client$ curl --proxy socks5h://127.0.0.1:7000/ https://wtfismyip.com/text
    201 201  ```
    202 202   
    203 203   
    skipped 143 lines
  • ■ ■ ■ ■ ■
    dns/dns.go
    skipped 100 lines
    101 101   } else {
    102 102   return NewName(bytes.Split(b, []byte(".")))
    103 103   }
    104  - return NewName(bytes.Split(b, []byte(".")))
    105 104  }
    106 105   
    107 106  // String returns a string representation of name, with labels separated by
    skipped 71 lines
    179 178  }
    180 179   
    181 180  // readName parses a DNS name from r. It leaves r positioned just after the
    182  -// parsed named.
     181 +// parsed name.
    183 182  func readName(r io.ReadSeeker) (Name, error) {
    184 183   var labels [][]byte
    185 184   // We limit the number of compression pointers we are willing to follow.
    skipped 372 lines
  • ■ ■ ■ ■ ■ ■
    dns/dns_test.go
    skipped 37 lines
    38 38   {[][]byte{[]byte("test")}, nil, "test"},
    39 39   {[][]byte{[]byte("a"), []byte("b"), []byte("c")}, nil, "a.b.c"},
    40 40   
    41  - {[][]byte{[]byte{}}, ErrZeroLengthLabel, ""},
    42  - {[][]byte{[]byte("a"), []byte{}, []byte("c")}, ErrZeroLengthLabel, ""},
     41 + {[][]byte{{}}, ErrZeroLengthLabel, ""},
     42 + {[][]byte{[]byte("a"), {}, []byte("c")}, ErrZeroLengthLabel, ""},
    43 43   
    44 44   // 63 octets.
    45 45   {[][]byte{[]byte("0123456789abcdef0123456789ABCDEF0123456789abcdef0123456789ABCDE")}, nil,
    skipped 213 lines
    259 259   // EOF while reading label.
    260 260   {0, "\x0aexample", io.ErrUnexpectedEOF},
    261 261   // EOF before second byte of pointer.
     262 + {0, "\xc0", io.ErrUnexpectedEOF},
    262 263   {0, "\x07example\xc0", io.ErrUnexpectedEOF},
    263 264   } {
    264 265   r := bytes.NewReader([]byte(test.input))
    skipped 144 lines
    409 410   
    410 411  func TestMessageWireFormatRoundTrip(t *testing.T) {
    411 412   for _, message := range []Message{
    412  - Message{
     413 + {
    413 414   ID: 0x1234,
    414 415   Flags: 0x0100,
    415 416   Question: []Question{
    skipped 84 lines
    500 501   // 255 bytes should be able to be encoded into 256 bytes.
    501 502   p = make([]byte, 255)
    502 503   encoded = EncodeRDataTXT(p)
    503  - t.Errorf("%x", encoded)
    504 504   if len(encoded) > 256 {
    505 505   t.Errorf("EncodeRDataTXT(%d bytes) returned %d bytes", len(p), len(encoded))
    506 506   }
    skipped 1 lines
    508 508   
    509 509  func TestRDataTXTRoundTrip(t *testing.T) {
    510 510   for _, p := range [][]byte{
    511  - []byte{},
     511 + {},
    512 512   []byte("\x00"),
    513 513   {
    514 514   0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
    skipped 26 lines
  • ■ ■ ■ ■ ■ ■
    dns/fuzz.go
     1 +// +build gofuzz
     2 + 
     3 +// Fuzzing driver for https://github.com/dvyukov/go-fuzz.
     4 +// go get -u github.com/dvyukov/go-fuzz/go-fuzz github.com/dvyukov/go-fuzz/go-fuzz-build
     5 +// $GOPATH/bin/go-fuzz-build
     6 +// $GOPATH/bin/go-fuzz
     7 +//
     8 +// Related link: https://blog.cloudflare.com/dns-parser-meet-go-fuzzer/
     9 + 
     10 +package dns
     11 + 
     12 +func Fuzz(data []byte) int {
     13 + msg, err := MessageFromWireFormat(data)
     14 + if err != nil {
     15 + return 0
     16 + }
     17 + _, err = msg.WireFormat()
     18 + if err != nil {
     19 + panic(err)
     20 + }
     21 + return 1 // prioritize this input
     22 +}
     23 + 
  • ■ ■ ■ ■
    dnstt-client/dns.go
    skipped 306 lines
    307 307   {
    308 308   Name: dns.Name{},
    309 309   Type: dns.RRTypeOPT,
    310  - Class: 4096, // requestor's UDP payload size
     310 + Class: 4096, // requester's UDP payload size
    311 311   TTL: 0, // extended RCODE and flags
    312 312   Data: []byte{},
    313 313   },
    skipped 74 lines
  • ■ ■ ■ ■ ■ ■
    dnstt-client/http.go
    skipped 25 lines
    26 26  // HTTPS (DoH). Its WriteTo and ReadFrom methods exchange DNS messages over HTTP
    27 27  // requests and responses.
    28 28  //
    29  -// HTTPPacketConn deals only with alreaday formatted DNS messages. It does not
     29 +// HTTPPacketConn deals only with already formatted DNS messages. It does not
    30 30  // handle encoding information into the messages. That is rather the
    31 31  // responsibility of DNSPacketConn.
    32 32  //
    skipped 65 lines
    98 98   default:
    99 99   // We primarily are thinking of 429 Too Many Requests here, but
    100 100   // any other unexpected response codes will also cause us to
    101  - // rate-limit ourself and emit a log message.
     101 + // rate-limit ourselves and emit a log message.
    102 102   // https://developers.google.com/speed/public-dns/docs/doh/#errors
    103 103   now := time.Now()
    104 104   var retryAfter time.Time
    skipped 67 lines
  • ■ ■ ■ ■ ■ ■
    dnstt-client/main.go
    skipped 95 lines
    96 96   err = nil
    97 97   }
    98 98   if err != nil {
    99  - log.Printf("stream %08x:%d copy stream←local: %v\n", conv, stream.ID(), err)
     99 + log.Printf("stream %08x:%d copy stream←local: %v", conv, stream.ID(), err)
    100 100   }
    101 101   local.CloseRead()
    102 102   stream.Close()
    skipped 6 lines
    109 109   err = nil
    110 110   }
    111 111   if err != nil && err != io.ErrClosedPipe {
    112  - log.Printf("stream %08x:%d copy local←stream: %v\n", conv, stream.ID(), err)
     112 + log.Printf("stream %08x:%d copy local←stream: %v", conv, stream.ID(), err)
    113 113   }
    114 114   local.CloseWrite()
    115 115   }()
    skipped 15 lines
    131 131   if mtu < 80 {
    132 132   return fmt.Errorf("domain %s leaves only %d bytes for payload", domain, mtu)
    133 133   }
    134  - log.Printf("effective MTU %d\n", mtu)
     134 + log.Printf("effective MTU %d", mtu)
    135 135   
    136 136   // Open a KCP conn on the PacketConn.
    137 137   conn, err := kcp.NewConn2(remoteAddr, nil, 0, 0, pconn)
    skipped 7 lines
    145 145   log.Printf("begin session %08x", conn.GetConv())
    146 146   // Permit coalescing the payloads of consecutive sends.
    147 147   conn.SetStreamMode(true)
    148  - // Disable the dynamic congestion window (limit only by the
    149  - // maximum of local and remote static windows).
     148 + // Disable the dynamic congestion window (limit only by the maximum of
     149 + // local and remote static windows).
    150 150   conn.SetNoDelay(
    151 151   0, // default nodelay
    152 152   0, // default interval
    skipped 32 lines
    185 185   defer local.Close()
    186 186   err := handle(local.(*net.TCPConn), sess, conn.GetConv())
    187 187   if err != nil {
    188  - log.Printf("handle: %v\n", err)
     188 + log.Printf("handle: %v", err)
    189 189   }
    190 190   }()
    191 191   }
    skipped 124 lines
  • ■ ■ ■ ■ ■
    dnstt-client/tls.go
    skipped 7 lines
    8 8   "log"
    9 9   "net"
    10 10   "sync"
     11 + "time"
    11 12   
    12 13   "www.bamsoftware.com/git/dnstt.git/turbotunnel"
    13 14  )
     15 + 
     16 +const dialTimeout = 30 * time.Second
    14 17   
    15 18  // TLSPacketConn is a TLS- and TCP-based transport for DNS messages, used for
    16 19  // DNS over TLS (DoT). Its WriteTo and ReadFrom methods exchange DNS messages
    17 20  // over a TLS channel, prefixing each message with a two-octet length field as
    18 21  // in DNS over TCP.
    19 22  //
    20  -// TLSPacketConn deals only with alreaday formatted DNS messages. It does not
     23 +// TLSPacketConn deals only with already formatted DNS messages. It does not
    21 24  // handle encoding information into the messages. That is rather the
    22 25  // responsibility of DNSPacketConn.
    23 26  //
    skipped 17 lines
    41 44   // becomes disconnected. We do the first dial here, outside the
    42 45   // goroutine, so that any immediate and permanent connection errors are
    43 46   // reported directly to the caller of NewTLSPacketConn.
     47 + dialer := &net.Dialer{
     48 + Timeout: dialTimeout,
     49 + }
    44 50   tlsConfig := &tls.Config{}
    45  - conn, err := tls.Dial("tcp", addr, tlsConfig)
     51 + conn, err := tls.DialWithDialer(dialer, "tcp", addr, tlsConfig)
    46 52   if err != nil {
    47 53   return nil, err
    48 54   }
    skipped 20 lines
    69 75   conn.Close()
    70 76   
    71 77   // Whenever the TLS connection dies, redial a new one.
    72  - conn, err = tls.Dial("tcp", addr, tlsConfig)
     78 + conn, err = tls.DialWithDialer(dialer, "tcp", addr, tlsConfig)
    73 79   if err != nil {
    74 80   log.Printf("tls.Dial: %v", err)
    75 81   break
    skipped 53 lines
  • ■ ■ ■ ■ ■ ■
    dnstt-server/main.go
    skipped 5 lines
    6 6  //
    7 7  // Example:
    8 8  // dnstt-server -gen-key -privkey-file server.key -pubkey-file server.pub
    9  -// dnstt-server -udp 127.0.0.1:5300 -privkey-file server.key t.example.com 127.0.0.1:8000
     9 +// dnstt-server -udp :53 -privkey-file server.key t.example.com 127.0.0.1:8000
    10 10  //
    11 11  // To generate a persistent server private key, first run with the -gen-key
    12 12  // option. By default the generated private and public keys are printed to
    skipped 10 lines
    23 23  // queries.
    24 24  //
    25 25  // The -mtu option controls the maximum size of response UDP payloads.
    26  -// Queries that do not advertise requestor support for responses of at least
     26 +// Queries that do not advertise requester support for responses of at least
    27 27  // this size at least this size will be responded to with a FORMERR. The default
    28 28  // value is maxUDPPayload.
    29 29  //
    skipped 41 lines
    71 71   // to be the query timeout of the Quad9 DoH server.
    72 72   // https://dnsencryption.info/imc19-doe.html Section 4.2, Finding 2.4
    73 73   maxResponseDelay = 1 * time.Second
     74 + 
     75 + // How long to wait for a TCP connection to upstream to be established.
     76 + upstreamDialTimeout = 30 * time.Second
    74 77  )
    75 78   
    76 79  var (
    skipped 104 lines
    181 184   
    182 185  // handleStream bidirectionally connects a client stream with a TCP socket
    183 186  // addressed by upstream.
    184  -func handleStream(stream *smux.Stream, upstream *net.TCPAddr, conv uint32) error {
    185  - conn, err := net.DialTCP("tcp", nil, upstream)
     187 +func handleStream(stream *smux.Stream, upstream string, conv uint32) error {
     188 + dialer := net.Dialer{
     189 + Timeout: upstreamDialTimeout,
     190 + }
     191 + upstreamConn, err := dialer.Dial("tcp", upstream)
    186 192   if err != nil {
    187 193   return fmt.Errorf("stream %08x:%d connect upstream: %v", conv, stream.ID(), err)
    188 194   }
    189  - defer conn.Close()
     195 + defer upstreamConn.Close()
     196 + upstreamTCPConn := upstreamConn.(*net.TCPConn)
    190 197   
    191 198   var wg sync.WaitGroup
    192 199   wg.Add(2)
    193 200   go func() {
    194 201   defer wg.Done()
    195  - _, err := io.Copy(stream, conn)
     202 + _, err := io.Copy(stream, upstreamTCPConn)
    196 203   if err == io.EOF {
    197 204   // smux Stream.Write may return io.EOF.
    198 205   err = nil
    199 206   }
    200 207   if err != nil {
    201  - log.Printf("stream %08x:%d copy stream←upstream: %v\n", conv, stream.ID(), err)
     208 + log.Printf("stream %08x:%d copy stream←upstream: %v", conv, stream.ID(), err)
    202 209   }
    203  - conn.CloseRead()
     210 + upstreamTCPConn.CloseRead()
    204 211   stream.Close()
    205 212   }()
    206 213   go func() {
    207 214   defer wg.Done()
    208  - _, err := io.Copy(conn, stream)
     215 + _, err := io.Copy(upstreamTCPConn, stream)
    209 216   if err == io.EOF {
    210 217   // smux Stream.WriteTo may return io.EOF.
    211 218   err = nil
    212 219   }
    213 220   if err != nil && err != io.ErrClosedPipe {
    214  - log.Printf("stream %08x:%d copy upstream←stream: %v\n", conv, stream.ID(), err)
     221 + log.Printf("stream %08x:%d copy upstream←stream: %v", conv, stream.ID(), err)
    215 222   }
    216  - conn.CloseWrite()
     223 + upstreamTCPConn.CloseWrite()
    217 224   }()
    218 225   wg.Wait()
    219 226   
    skipped 2 lines
    222 229   
    223 230  // acceptStreams wraps a KCP session in a Noise channel and an smux.Session,
    224 231  // then awaits smux streams. It passes each stream to handleStream.
    225  -func acceptStreams(conn *kcp.UDPSession, privkey, pubkey []byte, upstream *net.TCPAddr) error {
     232 +func acceptStreams(conn *kcp.UDPSession, privkey, pubkey []byte, upstream string) error {
    226 233   // Put a Noise channel on top of the KCP conn.
    227 234   rw, err := noise.NewServer(conn, privkey, pubkey)
    228 235   if err != nil {
    skipped 8 lines
    237 244   if err != nil {
    238 245   return err
    239 246   }
     247 + defer sess.Close()
    240 248   
    241 249   for {
    242 250   stream, err := sess.AcceptStream()
    skipped 11 lines
    254 262   }()
    255 263   err := handleStream(stream, upstream, conn.GetConv())
    256 264   if err != nil {
    257  - log.Printf("stream %08x:%d handleStream: %v\n", conn.GetConv(), stream.ID(), err)
     265 + log.Printf("stream %08x:%d handleStream: %v", conn.GetConv(), stream.ID(), err)
    258 266   }
    259 267   }()
    260 268   }
    skipped 1 lines
    262 270   
    263 271  // acceptSessions listens for incoming KCP connections and passes them to
    264 272  // acceptStreams.
    265  -func acceptSessions(ln *kcp.Listener, privkey, pubkey []byte, mtu int, upstream *net.TCPAddr) error {
     273 +func acceptSessions(ln *kcp.Listener, privkey, pubkey []byte, mtu int, upstream string) error {
    266 274   for {
    267 275   conn, err := ln.AcceptKCP()
    268 276   if err != nil {
    skipped 23 lines
    292 300   }()
    293 301   err := acceptStreams(conn, privkey, pubkey, upstream)
    294 302   if err != nil {
    295  - log.Printf("session %08x acceptStreams: %v\n", conn.GetConv(), err)
     303 + log.Printf("session %08x acceptStreams: %v", conn.GetConv(), err)
    296 304   }
    297 305   }()
    298 306   }
    skipped 54 lines
    353 361   }
    354 362   
    355 363   // Check for EDNS(0) support. Include our own OPT RR only if we receive
    356  - // one from the requestor.
     364 + // one from the requester.
    357 365   // https://tools.ietf.org/html/rfc6891#section-6.1.1
    358 366   // "Lack of presence of an OPT record in a request MUST be taken as an
    359  - // indication that the requestor does not implement any part of this
     367 + // indication that the requester does not implement any part of this
    360 368   // specification and that the responder MUST NOT include an OPT record
    361 369   // in its response."
    362 370   payloadSize := 0
    skipped 43 lines
    406 414   // There must be exactly one question.
    407 415   if len(query.Question) != 1 {
    408 416   resp.Flags |= dns.RcodeFormatError
    409  - log.Printf("FORMERR: too many questions (%d)", len(query.Question))
     417 + log.Printf("FORMERR: too few or too many questions (%d)", len(query.Question))
    410 418   return resp, nil
    411 419   }
    412 420   question := query.Question[0]
    skipped 47 lines
    460 468   // FORMERR MUST be returned."
    461 469   if payloadSize < maxUDPPayload {
    462 470   resp.Flags |= dns.RcodeFormatError
    463  - log.Printf("FORMERR: requestor payload size %d is too small (minimum %d)", payloadSize, maxUDPPayload)
     471 + log.Printf("FORMERR: requester payload size %d is too small (minimum %d)", payloadSize, maxUDPPayload)
    464 472   return resp, nil
    465 473   }
    466 474   
    skipped 232 lines
    699 707   {
    700 708   Name: dns.Name{},
    701 709   Type: dns.RRTypeOPT,
    702  - Class: queryLimit, // requestor's UDP payload size
     710 + Class: queryLimit, // requester's UDP payload size
    703 711   TTL: 0, // extended RCODE and flags
    704 712   Data: []byte{},
    705 713   },
    skipped 32 lines
    738 746   return low
    739 747  }
    740 748   
    741  -func run(privkey, pubkey []byte, domain dns.Name, upstream net.Addr, dnsConn net.PacketConn) error {
     749 +func run(privkey, pubkey []byte, domain dns.Name, upstream string, dnsConn net.PacketConn) error {
    742 750   defer dnsConn.Close()
    743 751   
    744 752   log.Printf("pubkey %x", pubkey)
    skipped 14 lines
    759 767   }
    760 768   return fmt.Errorf("maximum UDP payload size of %d leaves only %d bytes for payload", maxUDPPayload, mtu)
    761 769   }
    762  - log.Printf("effective MTU %d\n", mtu)
     770 + log.Printf("effective MTU %d", mtu)
    763 771   
    764 772   // Start up the virtual PacketConn for turbotunnel.
    765 773   ttConn := turbotunnel.NewQueuePacketConn(turbotunnel.DummyAddr{}, idleTimeout*2)
    skipped 3 lines
    769 777   }
    770 778   defer ln.Close()
    771 779   go func() {
    772  - err := acceptSessions(ln, privkey, pubkey, mtu, upstream.(*net.TCPAddr))
     780 + err := acceptSessions(ln, privkey, pubkey, mtu, upstream)
    773 781   if err != nil {
    774  - log.Printf("acceptSessions: %v\n", err)
     782 + log.Printf("acceptSessions: %v", err)
    775 783   }
    776 784   }()
    777 785   
    skipped 27 lines
    805 813   
    806 814  Example:
    807 815   %[1]s -gen-key -privkey-file server.key -pubkey-file server.pub
    808  - %[1]s -udp 127.0.0.1:5300 -privkey-file server.key t.example.com 127.0.0.1:8000
     816 + %[1]s -udp :53 -privkey-file server.key t.example.com 127.0.0.1:8000
    809 817   
    810 818  `, os.Args[0])
    811 819   flag.PrintDefaults()
    skipped 29 lines
    841 849   fmt.Fprintf(os.Stderr, "invalid domain %+q: %v\n", flag.Arg(0), err)
    842 850   os.Exit(1)
    843 851   }
    844  - upstream, err := net.ResolveTCPAddr("tcp", flag.Arg(1))
    845  - if err != nil {
    846  - fmt.Fprintf(os.Stderr, "cannot resolve %+q: %v\n", flag.Arg(1), err)
    847  - os.Exit(1)
     852 + upstream := flag.Arg(1)
     853 + // We keep upstream as a string in order to eventually pass it
     854 + // to net.Dial in handleStream. But for the sake of displaying
     855 + // an error or warning at startup, rather than only when the
     856 + // first stream occurs, we apply some parsing and name
     857 + // resolution checks here.
     858 + {
     859 + upstreamHost, _, err := net.SplitHostPort(upstream)
     860 + if err != nil {
     861 + // host:port format is required in all cases, so
     862 + // this is a fatal error.
     863 + fmt.Fprintf(os.Stderr, "cannot parse upstream address %+q: %v\n", upstream, err)
     864 + os.Exit(1)
     865 + }
     866 + upstreamIPAddr, err := net.ResolveIPAddr("ip", upstreamHost)
     867 + if err != nil {
     868 + // Failure to resolve the host portion is only a
     869 + // warning. The name will be re-resolved on each
     870 + // net.Dial in handleStream.
     871 + log.Printf("warning: cannot resolve upstream host %+q: %v", upstreamHost, err)
     872 + } else if upstreamIPAddr.IP == nil {
     873 + // Handle the special case of an empty string
     874 + // for the host portion, which resolves to a nil
     875 + // IP. This is a fatal error as we will not be
     876 + // able to dial this address.
     877 + fmt.Fprintf(os.Stderr, "cannot parse upstream address %+q: missing host in address\n", upstream)
     878 + os.Exit(1)
     879 + }
    848 880   }
    849 881   
    850 882   if udpAddr == "" {
    skipped 52 lines
  • ■ ■ ■ ■ ■ ■
    go.mod
    1 1  module www.bamsoftware.com/git/dnstt.git
    2 2   
     3 +go 1.11
     4 + 
    3 5  require (
    4  - github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6
    5  - github.com/xtaci/kcp-go/v5 v5.5.12
    6  - github.com/xtaci/smux v1.5.12
     6 + github.com/flynn/noise v1.0.0
     7 + github.com/xtaci/kcp-go/v5 v5.6.1
     8 + github.com/xtaci/smux v1.5.15
    7 9  )
    8 10   
  • ■ ■ ■ ■ ■
    go.sum
    1  -github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6 h1:u/UEqS66A5ckRmS4yNpjmVH56sVtS/RfclBAYocb4as=
    2  -github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6/go.mod h1:1i71OnUq3iUe1ma7Lr6yG6/rjvM3emb6yoL7xLFzcVQ=
    3  -github.com/klauspost/cpuid v1.2.2 h1:1xAgYebNnsb9LKCdLOvFWtAxGU/33mjJtyOVbmUa0Us=
    4  -github.com/klauspost/cpuid v1.2.2/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
    5  -github.com/klauspost/reedsolomon v1.9.3 h1:N/VzgeMfHmLc+KHMD1UL/tNkfXAt8FnUqlgXGIduwAY=
    6  -github.com/klauspost/reedsolomon v1.9.3/go.mod h1:CwCi+NUr9pqSVktrkN+Ondf06rkhYZ/pcNv7fu+8Un4=
    7  -github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
    8  -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
     1 +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
     2 +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
     3 +github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ=
     4 +github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag=
     5 +github.com/klauspost/cpuid v1.2.4/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
     6 +github.com/klauspost/cpuid v1.3.1 h1:5JNjFYYQrZeKRJ0734q51WCEEn2huer72Dc7K+R/b6s=
     7 +github.com/klauspost/cpuid v1.3.1/go.mod h1:bYW4mA6ZgKPob1/Dlai2LviZJO7KGI3uoWLd42rAQw4=
     8 +github.com/klauspost/reedsolomon v1.9.9 h1:qCL7LZlv17xMixl55nq2/Oa1Y86nfO8EqDfv2GHND54=
     9 +github.com/klauspost/reedsolomon v1.9.9/go.mod h1:O7yFFHiQwDR6b2t63KPUpccPtNdp5ADgh1gg4fd12wo=
     10 +github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
     11 +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
     12 +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
     13 +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
     14 +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
     15 +github.com/mmcloughlin/avo v0.0.0-20200803215136-443f81d77104 h1:ULR/QWMgcgRiZLUjSSJMU+fW+RDMstRdmnDWj9Q+AsA=
     16 +github.com/mmcloughlin/avo v0.0.0-20200803215136-443f81d77104/go.mod h1:wqKykBG2QzQDJEzvRkcS8x6MiSJkF52hXZsXcjaB3ls=
     17 +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
     18 +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
     19 +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
     20 +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
     21 +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
     22 +github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
     23 +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
    9 24  github.com/templexxx/cpu v0.0.1 h1:hY4WdLOgKdc8y13EYklu9OUTXik80BkxHoWvTO6MQQY=
    10 25  github.com/templexxx/cpu v0.0.1/go.mod h1:w7Tb+7qgcAlIyX4NhLuDKt78AHA5SzPmq0Wj6HiEnnk=
     26 +github.com/templexxx/cpu v0.0.7 h1:pUEZn8JBy/w5yzdYWgx+0m0xL9uk6j4K91C5kOViAzo=
     27 +github.com/templexxx/cpu v0.0.7/go.mod h1:w7Tb+7qgcAlIyX4NhLuDKt78AHA5SzPmq0Wj6HiEnnk=
    11 28  github.com/templexxx/xorsimd v0.4.1 h1:iUZcywbOYDRAZUasAs2eSCUW8eobuZDy0I9FJiORkVg=
    12 29  github.com/templexxx/xorsimd v0.4.1/go.mod h1:W+ffZz8jJMH2SXwuKu9WhygqBMbFnp14G2fqEr8qaNo=
    13  -github.com/tjfoc/gmsm v1.0.1 h1:R11HlqhXkDospckjZEihx9SW/2VW0RgdwrykyWMFOQU=
    14  -github.com/tjfoc/gmsm v1.0.1/go.mod h1:XxO4hdhhrzAd+G4CjDqaOkd0hUzmtPR/d3EiBBMn/wc=
    15  -github.com/xtaci/kcp-go/v5 v5.5.12 h1:iALGyvti/oBbl1TbVoUpHEUHCorDEb3tEKl1CPY3KXM=
    16  -github.com/xtaci/kcp-go/v5 v5.5.12/go.mod h1:H0T/EJ+lPNytnFYsKLH0JHUtiwZjG3KXlTM6c+Q4YUo=
     30 +github.com/tjfoc/gmsm v1.3.2 h1:7JVkAn5bvUJ7HtU08iW6UiD+UTmJTIToHCfeFzkcCxM=
     31 +github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w=
     32 +github.com/xtaci/kcp-go/v5 v5.6.1 h1:Pwn0aoeNSPF9dTS7IgiPXn0HEtaIlVb6y5UKWPsx8bI=
     33 +github.com/xtaci/kcp-go/v5 v5.6.1/go.mod h1:W3kVPyNYwZ06p79dNwFWQOVFrdcBpDBsdyvK8moQrYo=
     34 +github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae h1:J0GxkO96kL4WF+AIT3M4mfUVinOCPgf2uUWYFUzN0sM=
    17 35  github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE=
    18  -github.com/xtaci/smux v1.5.12 h1:n9OGjdqQuVZXLh46+L4IR5tR2wvuUFwRABnN/V55bIY=
    19  -github.com/xtaci/smux v1.5.12/go.mod h1:OMlQbT5vcgl2gb49mFkYo6SMf+zP3rcjcwQz7ZU7IGY=
     36 +github.com/xtaci/smux v1.5.15 h1:6hMiXswcleXj5oNfcJc+DXS8Vj36XX2LaX98udog6Kc=
     37 +github.com/xtaci/smux v1.5.15/go.mod h1:OMlQbT5vcgl2gb49mFkYo6SMf+zP3rcjcwQz7ZU7IGY=
     38 +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
     39 +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
     40 +golang.org/x/arch v0.0.0-20190909030613-46d78d1859ac/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4=
    20 41  golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
    21  -golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413 h1:ULYEB3JvPRE/IfO+9uO7vKV/xzVTO7XPAwm8xbf4w2g=
    22  -golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
     42 +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
     43 +golang.org/x/crypto v0.0.0-20191219195013-becbf705a915/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
     44 +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
     45 +golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
     46 +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w=
     47 +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
     48 +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
     49 +golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
     50 +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
    23 51  golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
    24  -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8=
    25  -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
     52 +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
     53 +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
     54 +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
     55 +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
     56 +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw=
     57 +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
     58 +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
     59 +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
     60 +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
    26 61  golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
    27 62  golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
    28  -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8 h1:JA8d3MPx/IToSyXZG/RhwYEtfrKO1Fxrqe8KrkiLXKM=
    29  -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
     63 +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
     64 +golang.org/x/sys v0.0.0-20200808120158-1030fc2bf1d9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
     65 +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw=
     66 +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
     67 +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
    30 68  golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
     69 +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
     70 +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
     71 +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
     72 +golang.org/x/tools v0.0.0-20200425043458-8463f397d07c/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
     73 +golang.org/x/tools v0.0.0-20200808161706-5bf02b21f123 h1:4JSJPND/+4555t1HfXYF4UEqDqiSKCgeV0+hbA8hMs4=
     74 +golang.org/x/tools v0.0.0-20200808161706-5bf02b21f123/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
     75 +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
     76 +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
     77 +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
     78 +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
     79 +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
     80 +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
     81 +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
     82 +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
     83 +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
     84 +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
     85 +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
    31 86   
  • ■ ■ ■ ■ ■ ■
    man/dnstt-client.1
     1 +.\" https://man.openbsd.org/mdoc.7
     2 +.Dd 2020-08-30
     3 +.Dt DNSTT-CLIENT 1
     4 +.Os
     5 + 
     6 + 
     7 +.Sh NAME
     8 + 
     9 +.Nm dnstt-client
     10 +.Nd DNS tunnel client
     11 + 
     12 + 
     13 +.Sh SYNOPSIS
     14 + 
     15 +.Nm
     16 +.Op Fl doh Ar URL | Fl dot Ar HOST : Ns Ar PORT | Fl udp Ar HOST : Ns Ar PORT
     17 +.Op Fl pubkey Ar HEX | Fl pubkey-file Ar FILENAME
     18 +.Ar DOMAIN
     19 +.Ar LOCALADDR : Ns Ar LOCALPORT
     20 + 
     21 + 
     22 +.Sh DESCRIPTION
     23 + 
     24 +.Nm
     25 +is the client portion of a DNS tunnel.
     26 +It receives TCP connections at
     27 +.Ar LOCALADDR : Ns Ar LOCALPORT
     28 +and forwards them,
     29 +encoded as a sequence of DNS messages
     30 +and via a recursive resolver,
     31 +to an instance of
     32 +.Xr dnstt-server 1
     33 +running as the authoritative name server for
     34 +.Ar DOMAIN .
     35 +The DNS messages may be carried over
     36 +DNS over HTTPS,
     37 +DNS over TLS,
     38 +or classical DNS over UDP.
     39 + 
     40 +.Pp
     41 +You must use exactly one of the
     42 +.Fl doh ,
     43 +.Fl dot ,
     44 +or
     45 +.Fl udp
     46 +options,
     47 +to specify what form of DNS to use:
     48 + 
     49 +.Bl -tag
     50 + 
     51 +.It Fl doh Ar URL
     52 +Use DNS over HTTPS.
     53 +.Ar URL
     54 +is the URL of the DNS over HTTPS resolver,
     55 +including the
     56 +.Ql /dns-query
     57 +path if used by the resolver.
     58 + 
     59 +.Pp
     60 +See
     61 +.Lk https://github.com/curl/curl/wiki/DNS-over-HTTPS#publicly-available-servers
     62 +for a list of public DNS over HTTPS resolvers.
     63 + 
     64 +.It Fl dot Ar HOST : Ns Ar PORT
     65 +Use DNS over TLS.
     66 +.Ar HOST
     67 +and
     68 +.Ar PORT
     69 +are the TCP address of the DNS over TLS resolver.
     70 +.Ar PORT
     71 +is normally 853.
     72 + 
     73 +.Pp
     74 +See
     75 +.Lk https://dnsprivacy.org/wiki/display/DP/DNS+Privacy+Public+Resolvers#DNSPrivacyPublicResolvers-DNS-over-TLS%28DoT%29
     76 +for a list of public DNS over TLS resolvers.
     77 + 
     78 +.It Fl udp Ar HOST : Ns Ar PORT
     79 +Use DNS over UDP.
     80 +.Ar HOST
     81 +and
     82 +.Ar PORT
     83 +are the UDP address of the DNS resolver.
     84 +.Ar PORT
     85 +is normally 53.
     86 + 
     87 +With
     88 +.Fl udp ,
     89 +you have the option of communicating directly with an instance of
     90 +.Xr dnstt-server 1 ,
     91 +without going through a recursive resolver.
     92 +That is,
     93 +.Ar HOST : Ns Ar PORT
     94 +may point directly at the authoritative name server for
     95 +.Ar DOMAIN ,
     96 +where
     97 +.Xr dnstt-server 1
     98 +is running.
     99 + 
     100 +.El
     101 + 
     102 +.Pp
     103 +In addition, you must use one of the
     104 +.Fl pubkey
     105 +or
     106 +.Fl pubkey-file
     107 +options to specify the public key used
     108 +for authenticating the server and encrypting the channel.
     109 +The public key should have been generated by
     110 +.Ql dnstt-server -gen-key .
     111 +.Xr dnstt-server 1
     112 +prints its public key at the beginning of its log output.
     113 + 
     114 +.Bl -tag
     115 + 
     116 +.It Fl pubkey Ar HEX
     117 +.Ar HEX
     118 +is a string of 64 hexadecimal digits.
     119 + 
     120 +.It Fl pubkey-file Ar FILENAME
     121 +.Ar FILENAME
     122 +is the name of a file containing
     123 +64 hexadecimal digits and an
     124 +optional training newline character.
     125 + 
     126 +.El
     127 + 
     128 +.Sh EXAMPLES
     129 + 
     130 +Tunnel through the DNS over HTTPS resolver at
     131 +.Cm https://resolver.example/dns-query
     132 +to the authoritative name server for
     133 +.Cm t.example.com .
     134 +Listen locally at
     135 +.Cm 127.0.0.1:7000
     136 +for connections to forward through the tunnel.
     137 +Use the server public key stored in the file
     138 +.Cm server.pub .
     139 + 
     140 +.Bd -literal -offset indent
     141 +dnstt-client -doh https://resolver.example/dns-query -pubkey-file server.pub t.example.com 127.0.0.1:7000
     142 +.Ed
     143 + 
     144 +.Pp
     145 +Tunnel through the DNS over TLS resolver at
     146 +.Cm resolver.example:853
     147 +to the authoritative name server for
     148 +.Cm t.example.com .
     149 +Listen locally at
     150 +.Cm 127.0.0.1:7000
     151 +for connections to forward through the tunnel.
     152 +Use the given hex string as the server public key.
     153 + 
     154 +.Bd -literal -offset indent
     155 +dnstt-client -dot resolver.example:853 -pubkey 14ca15f53660e248d289d9302f992c4bee518f2361d6343dafa7b417b5a3d752 t.example.com 127.0.0.1:7000
     156 +.Ed
     157 + 
     158 + 
     159 +.Sh DIAGNOSTICS
     160 + 
     161 +.Nm
     162 +writes running logs to standard error.
     163 + 
     164 +At startup,
     165 +.Nm
     166 +logs the amount of useful payload capacity that can be stored
     167 +in each DNS query, after accounting for the overhead of encoding.
     168 +This number will vary depending on the length of
     169 +.Ar DOMAIN .
     170 + 
     171 +.Dl effective MTU 128
     172 + 
     173 + 
     174 +.Sh BUGS
     175 + 
     176 +.Nm
     177 +has a distinctive TLS fingerprint
     178 +and is probably easy to block on that basis.
     179 + 
     180 + 
     181 +.Sh SECURITY CONSIDERATIONS
     182 + 
     183 +The
     184 +.Fl udp
     185 +option is not covert,
     186 +and is intended for debugging and special configurations.
     187 +Only the
     188 +.Fl doh
     189 +and
     190 +.Fl dot
     191 +modes provide protection against detection of the tunnel,
     192 +because they encrypt DNS messages between
     193 +.Nm
     194 +and the recursive resolver.
     195 +The
     196 +.Fl udp
     197 +mode sends plaintext DNS messages,
     198 +which reveal the use of a DNS tunnel by their special format.
     199 + 
     200 +Even with
     201 +.Fl doh
     202 +or
     203 +.Fl dot ,
     204 +it may be possible for an observer to infer
     205 +the use of a tunnel
     206 +by traffic metadata features such as
     207 +traffic volume and timing.
     208 +The recursive resolver can see the plaintext of DNS messages
     209 +and is always in a position to easily detect the use of a tunnel.
     210 + 
     211 +But even if the use of a tunnel is detected, the
     212 +.Em contents
     213 +of the tunnel remain encrypted and authenticated.
     214 +The end-to-end encryption and authentication of the tunnel is a separate layer,
     215 +independent of the encryption
     216 +provided by DNS over HTTPS or DNS over TLS.
     217 + 
     218 + 
     219 +.Sh SEE ALSO
     220 + 
     221 +.Xr dnstt-server 1
     222 + 
     223 +.Lk https://www.bamsoftware.com/software/dnstt/
     224 + 
     225 + 
     226 +.Sh AUTHORS
     227 + 
     228 +.An David Fifield Aq Mt [email protected]
     229 + 
  • ■ ■ ■ ■ ■ ■
    man/dnstt-server.1
     1 +.\" https://man.openbsd.org/mdoc.7
     2 +.Dd 2020-08-30
     3 +.Dt DNSTT-SERVER 1
     4 +.Os
     5 + 
     6 + 
     7 +.Sh NAME
     8 + 
     9 +.Nm dnstt-server
     10 +.Nd DNS tunnel server
     11 + 
     12 + 
     13 +.Sh SYNOPSIS
     14 + 
     15 +.Nm
     16 +.Fl gen-key
     17 +.Op Fl privkey-file Ar FILENAME
     18 +.Op Fl pubkey-file Ar FILENAME
     19 + 
     20 +.Nm
     21 +.Fl udp Ar ADDR : Ns Ar PORT
     22 +.Op Fl privkey Ar HEX | Fl privkey-file Ar FILENAME
     23 +.Op Fl mtu Ar MTU
     24 +.Ar DOMAIN
     25 +.Ar UPSTREAMADDR : Ns Ar UPSTREAMPORT
     26 + 
     27 + 
     28 +.Sh DESCRIPTION
     29 + 
     30 +.Nm
     31 +is the server portion of a DNS tunnel.
     32 +It receives DNS over UDP messages at
     33 +.Ar ADDR : Ns Ar PORT ,
     34 +decodes the streams they contain,
     35 +and forwards the streams as TCP connections to
     36 +.Ar UPSTREAMADDR : Ns Ar UPSTREAMPORT .
     37 +.Nm acts as the authoritative name server for
     38 +.Ar DOMAIN
     39 +and communicates with an instance of
     40 +.Xr dnstt-client 1
     41 +via a recursive resolver.
     42 + 
     43 +.Ss GENERATING A SERVER KEYPAIR
     44 + 
     45 +The tunnel client
     46 +encrypts and authenticates the tunneled connection
     47 +using the server's public key.
     48 +To generate a server keypair, use the
     49 +.Fl gen-key
     50 +option.
     51 +Use the
     52 +.Fl privkey-file
     53 +and
     54 +.Fl pubkey-file
     55 +options to save the generated private key,
     56 +public key, or both,
     57 +to a file.
     58 + 
     59 +.Bl -tag
     60 + 
     61 +.It Fl gen-key
     62 +Generate a server keypair.
     63 + 
     64 +.It Fl privkey-file Ar FILENAME
     65 +With
     66 +.Fl gen-key ,
     67 +save the generated private key to
     68 +.Ar FILENAME .
     69 + 
     70 +.It Fl pubkey-file Ar FILENAME
     71 +With
     72 +.Fl gen-key ,
     73 +save the generated public key to
     74 +.Ar FILENAME .
     75 + 
     76 +.El
     77 + 
     78 +.Pp
     79 +On the server, you only need to store the private key, because
     80 +.Nm
     81 +can derive the public key from the private key.
     82 +The client only needs to have the server's public key
     83 +and should not know the servers private key.
     84 + 
     85 +.Ss RUNNING THE SERVER
     86 + 
     87 +The required
     88 +.Fl udp
     89 +option specifies the UDP address on which
     90 +.Nm
     91 +listens for incoming DNS messages.
     92 + 
     93 +.Bl -tag
     94 +.It Fl udp Ar ADDR : Ns Ar PORT
     95 +Accept DNS messages at the given address.
     96 +.Ar PORT
     97 +must typically be 53
     98 +when operating with a recursive intermediate resolver,
     99 +unless you have made some other provision for forwarding
     100 +port 53 to
     101 +.Ar PORT .
     102 + 
     103 +.El
     104 + 
     105 +.Pp
     106 +Specify the server's persistent keypair using the
     107 +.Fl privkey
     108 +or
     109 +.Fl privkey-file
     110 +options.
     111 +If you do not use one of these options,
     112 +.Nm
     113 +generates a temporary keypair
     114 +and logs the public key to standard error.
     115 + 
     116 +.Bl -tag
     117 + 
     118 +.It Fl privkey Ar HEX
     119 +.Ar HEX
     120 +is a string of 64 hexadecimal digits.
     121 + 
     122 +.It Fl privkey-file Ar FILENAME
     123 +.Ar FILENAME
     124 +is the name of a file containing
     125 +64 hexadecimal digits and an
     126 +optional training newline character.
     127 + 
     128 +.El
     129 + 
     130 +.Pp
     131 +In some situations, you may have to use the
     132 +.Fl mtu
     133 +option to control the maximum UDP payload size.
     134 + 
     135 +.Bl -tag
     136 + 
     137 +.It Fl mtu Ar MTU
     138 +Never send UDP payloads larger than
     139 +.Ar MTU
     140 +bytes.
     141 +The default
     142 +.Ar MTU
     143 +is 1232, but some recursive resolver only support a maximum of 512.
     144 +You will know you need to use the
     145 +.Fl mtu
     146 +option when you see messages like this on standard error:
     147 +.Dl FORMERR: requester payload size 512 is too small (minimum 1232)
     148 + 
     149 +.El
     150 + 
     151 + 
     152 +.Sh EXAMPLES
     153 + 
     154 +Generate a keypair.
     155 +Save the private key to the file
     156 +.Cm server.key
     157 +and the public key to
     158 +.Cm server.pub .
     159 +Next, you would typically copy
     160 +.Pa server.pub
     161 +to the client.
     162 + 
     163 +.Bd -literal -offset indent
     164 +dnstt-server -gen-key -privkey-file server.key -pubkey-file server.pub
     165 +.Ed
     166 + 
     167 +.Pp
     168 +Accept DNS messages at the UDP address
     169 +.Cm 0.0.0.0:53 ,
     170 +decode the streams contained therein,
     171 +and forward the streams as TCP connections to
     172 +.Cm 127.0.0.1:8000 .
     173 +Read the private key from the file
     174 +.Cm server.key
     175 +and derive the public key from it.
     176 +The server should be configured to be
     177 +the authoritative name server for the domain
     178 +.Cm t.example.com .
     179 + 
     180 +.Bd -literal -offset indent
     181 +dnstt-server -udp 127.0.0.1:53 -privkey-file server.key t.example.com 127.0.0.1:8000
     182 +.Ed
     183 + 
     184 + 
     185 +.Sh DIAGNOSTICS
     186 + 
     187 +.Nm
     188 +writes running logs to standard error.
     189 + 
     190 +At startup,
     191 +.Nm
     192 +logs its public key.
     193 +This string can be used with the
     194 +.Fl -pubkey
     195 +option in
     196 +.Xr dnstt-client 1 .
     197 + 
     198 +.Dl pubkey 14ca15f53660e248d289d9302f992c4bee518f2361d6343dafa7b417b5a3d752
     199 + 
     200 +.Pp
     201 +At startup,
     202 +.Nm
     203 +logs the amount of useful payload capacity that can be stored
     204 +in each DNS response, after accounting for the overhead of encoding.
     205 +This number will vary depending on the length of
     206 +.Ar DOMAIN
     207 +and the value of
     208 +.Ar MTU .
     209 + 
     210 +.Dl effective MTU 932
     211 + 
     212 + 
     213 +.Pp
     214 +If the recursive resolver's stated maximum UDP payload size
     215 +is smaller than
     216 +.Ar MTU ,
     217 +.Nm
     218 +will log a message like this,
     219 +which tells you that you need to use the
     220 +.Fl mtu
     221 +option.
     222 + 
     223 +.Dl FORMERR: requester payload size 512 is too small (minimum 1232)
     224 + 
     225 + 
     226 +.Sh SEE ALSO
     227 + 
     228 +.Xr dnstt-client 1
     229 + 
     230 +.Lk https://www.bamsoftware.com/software/dnstt/
     231 + 
     232 + 
     233 +.Sh AUTHORS
     234 + 
     235 +.An David Fifield Aq Mt [email protected]
     236 + 
  • ■ ■ ■ ■ ■
    noise/noise.go
    skipped 110 lines
    111 111   if n > 4096 {
    112 112   n = 4096
    113 113   }
    114  - err := writeMessage(s.ReadWriteCloser, s.sendCipher.Encrypt(nil, nil, p[:n]))
     114 + msg, err := s.sendCipher.Encrypt(nil, nil, p[:n])
     115 + if err != nil {
     116 + return total, err
     117 + }
     118 + err = writeMessage(s.ReadWriteCloser, msg)
    115 119   if err != nil {
    116 120   return total, err
    117 121   }
    skipped 159 lines
    277 281   return key, err
    278 282  }
    279 283   
    280  -// DecodeKey decodes a hex-encoded private or public key.
     284 +// EncodeKey encodes a hex-encoded private or public key.
    281 285  func EncodeKey(key []byte) string {
    282 286   return hex.EncodeToString(key)
    283 287  }
    skipped 1 lines
Please wait...
Page is in error, reload to recover