SkillAgentSearch skills...

Dnstt

Mirror of https://www.bamsoftware.com/git/dnstt.git + SIP003 plugin; DEPRECATED please see https://github.com/Mygod/slipstream-rust

Install / Use

/learn @Mygod/Dnstt
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Userspace DNS tunnel with support for DoH and DoT https://www.bamsoftware.com/software/dnstt/ David Fifield david@bamsoftware.com Public domain

dnstt is a DNS tunnel with these features:

  • Works over DNS over HTTPS (DoH) and DNS over TLS (DoT) as well as plaintext UDP DNS.
  • Embeds a sequencing and session protocol (KCP/smux), which means that the client does not have to wait for a response before sending more data, and any lost packets are automatically retransmitted.
  • Encrypts the contents of the tunnel and authenticates the server by public key.

dnstt is an application-layer tunnel that runs in userspace. It doesn't provide a TUN/TAP interface; it only hooks up a local TCP port with a remote TCP port (like netcat or ssh -L) by way of a DNS resolver. It does not itself provide a SOCKS or HTTP proxy interface, but you can get the same effect by running a proxy on the tunnel server and having the tunnel terminate at the proxy.

.------.  |            .---------.             .------.
|tunnel|  |            | public  |             |tunnel|
|client|<---DoH/DoT--->|recursive|<--UDP DNS-->|server|
'------'  |c           |resolver |             '------'
   |      |e           '---------'                |
.------.  |n                                   .------.
|local |  |s                                   |remote|
| app  |  |o                                   | app  |
'------'  |r                                   '------'

DNS zone setup

Because the server side of the tunnel acts like an authoritative name server, you need to own a domain name and set up a subdomain for the tunnel. Let's say your domain name is example.com and your server's IP addresses are 203.0.113.2 and 2001:db8::2. Go to your name registrar and add three new records:

A	tns.example.com	points to 203.0.113.2
AAAA	tns.example.com	points to 2001:db8::2
NS	t.example.com	is managed by tns.example.com

The labels tns and t can be anything you want, but the tns label should not be a subdomain of the t label (that space is reserved for the contents of the tunnel), and the t label should be short (because there is limited space available in a DNS message, and the domain name takes up part of that space).

Now, when a recursive DNS resolver receives a query for a name like aaaa.t.example.com, it will forward the query to the tunnel server at 203.0.113.2 or 2001:db8::2.

Tunnel server setup

Compile the server:

tunnel-server$ cd dnstt-server
tunnel-server$ go build

First you need to generate the server keypair that will be used to authenticate the server and encrypt the tunnel.

tunnel-server$ ./dnstt-server -gen-key -privkey-file server.key -pubkey-file server.pub
privkey written to server.key
pubkey  written to server.pub

Run the server. You need to provide an address that will listen for UDP DNS packets (:5300), the private key file (server.key), the root of the DNS zone (t.example.com), and a TCP address to which incoming tunnel streams will be forwarded (127.0.0.1:8000).

tunnel-server$ ./dnstt-server -udp :5300 -privkey-file server.key t.example.com 127.0.0.1:8000

The tunnel server needs to be able to receive packets on an external port 53. You can have it listen on port 53 directly using -udp :53, but that requires the program to run as root. It is better to run the program as an ordinary user and have it listen on an unprivileged port (:5300 above), and port-forward port 53 to it. On Linux, use these commands to forward external port 53 to localhost port 5300:

tunnel-server$ sudo iptables -I INPUT -p udp --dport 5300 -j ACCEPT
tunnel-server$ sudo iptables -t nat -I PREROUTING -i eth0 -p udp --dport 53 -j REDIRECT --to-ports 5300
tunnel-server$ sudo ip6tables -I INPUT -p udp --dport 5300 -j ACCEPT
tunnel-server$ sudo ip6tables -t nat -I PREROUTING -i eth0 -p udp --dport 53 -j REDIRECT --to-ports 5300

You need to also run something for the tunnel server to connect to. It can be a proxy server or anything else. For testing, you can use an Ncat listener:

tunnel-server$ ncat -l -k -v 127.0.0.1 8000

Tunnel client setup

Compile the client:

tunnel-client$ cd dnstt-client
tunnel-client$ go build

Copy the server.pub file from the server to the client. You don't need server.key on the client; leave it on the server.

Choose a public DoH or DoT resolver. There is a list of DoH resolvers here:

  • https://github.com/curl/curl/wiki/DNS-over-HTTPS#publicly-available-servers

And DoT resolvers here:

  • https://dnsprivacy.org/wiki/display/DP/DNS+Privacy+Public+Resolvers#DNSPrivacyPublicResolvers-DNS-over-TLS%28DoT%29
  • https://dnsencryption.info/imc19-doe.html

To run the tunnel client using DoH, you need to provide the URL of the DoH resolver (https://doh.example/dns-query), the server's public key files (server.pub), the root of the DNS zone (t.example.com), and the local TCP port that will receive connections and forward them through the tunnel (127.0.0.1:7000):

tunnel-client$ ./dnstt-client -doh https://doh.example/dns-query -pubkey-file server.pub t.example.com 127.0.0.1:7000

For DoT, it's the same, but use the -dot option instead:

tunnel-client$ ./dnstt-client -dot dot.example:853 -pubkey-file server.pub t.example.com 127.0.0.1:7000

Once the tunnel client is running, you can connect to the local end of the tunnel, type something, and see it appear at the remote end.

tunnel-client$ ncat -v 127.0.0.1 7000

The client also has a plaintext UDP mode that can work through a recursive resolver or directly to the tunnel server (-udp tns.example.com), but it does not provide any covertness for the tunnel and should only be used for testing.

How to make a proxy

dnstt is only a tunnel; it's up to you what you want to connect to it. You can make the tunnel work like an ordinary SOCKS or HTTP proxy by having the tunnel server forward to a standard proxy server. There are many ways to set it up; here are some examples.

Ncat HTTP proxy

Ncat has a simple built-in HTTP/HTTPS proxy, good for testing. Be aware that Ncat's proxy isn't intended for use by untrusted clients; it won't prevent them from connecting to localhost ports on the tunnel server, for example.

tunnel-server$ ncat -l -k --proxy-type http 127.0.0.1 8000
tunnel-server$ ./dnstt-server -udp :5300 -privkey-file server.key t.example.com 127.0.0.1:8000

On the client, have the tunnel client listen on 127.0.0.1:7000, and configure your applications to use 127.0.0.1:7000 as an HTTP proxy.

tunnel-client$ ./dnstt-client -doh https://doh.example/dns-query -pubkey-file server.pub t.example.com 127.0.0.1:7000
tunnel-client$ curl --proxy http://127.0.0.1:7000/ https://wtfismyip.com/text

SSH SOCKS proxy

OpenSSH has a built-in SOCKS proxy, which makes it easy to add a SOCKS proxy to a server that already has sshd installed.

On the server, make a localhost SSH connection, using the -D option to open a SOCKS listener at port 8000. Then configure the tunnel server to forward incoming connections to port 8000. Have the tunnel client listen on its own local port 7000.

tunnel-server$ ssh -N -D 127.0.0.1:8000 -o NoHostAuthenticationForLocalhost=yes 127.0.0.1
# Enter the password of the local user on tunnel-server
tunnel-server$ ./dnstt-server -udp :5300 -privkey-file server.key t.example.com 127.0.0.1:8000
tunnel-client$ ./dnstt-client -doh https://doh.example/dns-query -pubkey-file server.pub t.example.com 127.0.0.1:7000
tunnel-client$ curl --proxy socks5h://127.0.0.1:7000/ https://wtfismyip.com/text

The above configuration, by locating the SOCKS client port on the server, makes a SOCKS proxy that can be used by anyone with access to the DNS tunnel. Alternatively, you can make an SSH SOCKS proxy for your own private use, with the SSH connection going through the tunnel and the SOCKS client port being located at the client.

Let's assume you have the SSH details configured so that you can run ssh tunnel-server on the tunnel client. Make sure AllowTcpForwarding is set to yes (the default value) in sshd_config. Run the tunnel server and have it forward directly to the SSH port.

tunnel-server$ ./dnstt-server -udp :5300 -privkey-file server.key t.example.com 127.0.0.1:22

Run the tunnel client with the local listening port at 127.0.0.1:7000. The HostKeyAlias ssh option lets you connect to the SSH server as if it were located at 127.0.0.1:8000. Replace tunnel-server with the hostname or IP address of the SSH server.

tunnel-client$ ./dnstt-client -doh https://doh.example/dns-query -pubkey-file server.pub t.example.com 127.0.0.1:8000
tunnel-client$ ssh -N -D 127.0.0.1:7000 -o HostKeyAlias=tunnel-server -p 8000 127.0.0.1
tunnel-client$ curl --proxy socks5h://127.0.0.1:7000/ https://wtfismyip.com/text

Tor bridge

You can run a Tor bridge on the tunnel server and tunnel the connection to the bridge with dnstt, using dnstt as like a pluggable transport. The Tor client provides a SOCKS interface that other programs can use. Let's say your Tor bridge's ORPort is 9001.

tunnel-server$ ./dnstt-server -udp :5300 -privkey-file server.key t.example.com 127.0.0.1:9001
tunnel-client$ ./dnstt-client -doh https://doh.example/dns-query -pubkey-file server.pub t.example.com 127.0.0.1:7000

Add a Bridge line to /etc/tor/torrc, or paste it into Tor Browser. You can get FINGERPRINT from /var/lib/tor/fingerprint on the bridge.

Bridge 127.0.0.1:7000 FINGERPRINT

If you use a system tor, the client SOCKS port will be 127.0.0.1:9050. If you use Tor Browser, it will be 127.0.0.1:9150.

Covertness

Support for DoH and DoT is only to make it more difficult for a local observer to see that a DNS tunnel is being used, not for the overall security of the connection. There is a separate encryption layer inside the tunnel that protects the contents of the tunnel from the resolver itse

View on GitHub
GitHub Stars111
CategoryDevelopment
Updated3d ago
Forks29

Languages

Go

Security Score

95/100

Audited on Mar 27, 2026

No findings