Testing branch for uTLS support

I have a branch for adding uTLS support to dnstt’s DoH and DoT modes. uTLS (NTC thread) is a package that allows changing a network program’s TLS fingerprint so that it resembles other common TLS applications. This intention behind this change is to make dnstt harder to block by the Go crypto/tls fingerprint.

I invite you to test and comment on the utls branch before I merge it into the mainline. To check out and build the utls branch (currently at 98bdffa1, cumulative diff):

$ git clone -b utls https://www.bamsoftware.com/git/dnstt.git
$ cd dnstt/dnstt-client
$ go build

To actually use the DNS tunnel, you will need to set up a server, but you do not need to set up a server if you only want to look at packet captures of the TLS fingerprints.

By default, the program chooses a TLS fingerprint randomly from a weighted distribution, which you can see with dnstt-client -help. A log message will show what fingerprint was chosen.

$ go run ../dnstt-server/ -gen-key -privkey-file server.key -pubkey-file server.pub
$ ./dnstt-client -doh https://dns.google/dns-query -pubkey-file server.pub t.example.com 127.0.0.1:7000
2022/01/03 03:57:20 uTLS fingerprint Firefox 65
$ ./dnstt-client -dot dns.google:853 -pubkey-file server.pub t.example.com 127.0.0.1:7000
2022/01/03 04:08:08 uTLS fingerprint iOS 12.1

You can use the -utls to control the weighted distribution of TLS fingerprints. Examples:

-utls 5*firefox,2*chrome,1*ios  # 62.5% latest Firefox, 25% latest Chrome, 12.5% latest iOS
-utls iOS_12_1                  # 100% iOS 12.1
-utls none                      # disable uTLS and use the Go crypto/tls fingerprint

Not all fingerprints are compatible with all servers. For example,

$ ./dnstt-client -utls Chrome_70 -doh https://dns.google/dns-query -pubkey-file server.pub t.example.com 127.0.0.1:7000
2022/01/03 04:03:39 sendLoop: Post "https://dns.google/dns-query": remote error: tls: unexpected message
$ ./dnstt-client -utls Chrome_70 -dot dns.google:853 -pubkey-file server.pub t.example.com 127.0.0.1:7000
2022/01/03 04:07:51 recvLoop: remote error: tls: unexpected message

dnstt-client -help shows what fingerprints are available:

  none Firefox Firefox_55 Firefox_56 Firefox_63 Firefox_65 Chrome
  Chrome_58 Chrome_62 Chrome_70 Chrome_72 Chrome_83 iOS iOS_11_1
  iOS_12_1

-utls none will have the best compatibility, but it is the least covert.

Some feedback I’m looking for is whether any of the TLS fingerprints chosen by default are not compatible with DNS resolvers that people are using.

I tried adding a call to utls.EnableWeakCiphers to increase compatibility, but it still fails in the same way as without:

fingerprint -doh dns.google -dot dns.google -doh 1.1.1.1 -dot 1.1.1.1
Firefox_55 ok ok ok ok
Firefox_56 ok ok ok ok
Firefox_63 ok ok ok ok
Firefox_65 ok ok ok ok
Chrome_58 ERROR ERROR ok ok
Chrome_62 ERROR ERROR ok ok
Chrome_70 ERROR ERROR ERROR ok
Chrome_72 ok ok ERROR ok
Chrome_83 ok ok ERROR ok
iOS_11_1 ok ok ok ok
iOS_12_1 ok ok ok ok