Opened 8 months ago

Last modified 7 months ago

#25874 new project

DNS-based rendezvous for Snowflake

Reported by: dcf Owned by:
Priority: Medium Milestone:
Component: Obfuscation/Snowflake Version:
Severity: Normal Keywords:
Cc: dcf, arlolra Actual Points:
Parent ID: Points:
Reviewer: Sponsor:

Description

From #25594:
An idea to use DNS over HTTPS:
https://groups.google.com/forum/#!topic/traffic-obf/ZQohlnIEWM4

The circumvention idea is to take any existing DNS tunneling scheme and send it through DNS over HTTPS. To be a bit more specific: you send recursive DNS queries (encoding your upstream traffic) to the DNS-over-HTTPS server, which then forwards the queries to another specialized server that decodes them and proxies the data they contain.

Even if not a general-purpose transport, DNS-over-HTTPS could be an ideal rendezvous mechanism for a system like Snowflake or Moat. One where you only need to send/receive a small amount of very hard-to-block data in order to bootstrap a connection.

The way I see it, there are two parts of this:

  1. Using DNS as an underlying transport: the client sends a DNS request containing its encoded offer; the broker sends back a DNS response containing an encoded proxy answer.
  2. Sending via DNS-over-HTTPS in order to avoid blocking of the DNS messages themselves.

Child Tickets

Change History (4)

comment:1 Changed 8 months ago by dcf

For testing purposes, I set up snowflake-broker.bamsoftware.com to be the authoritative nameserver for the subdomain test.bamsoftware.com. (I think; I'm not too good at this DNS stuff.) There is no responder running there yet, but you can use tcpdump on the broker to watch requests arrive:

tcpdump -n -X port 53

Then, from somewhere else, try a normal DNS query. In the tcpdump you should see requests arrive from your ISP's recursive nameserver.

dig message${RANDOM}.test.bamsoftware.com

Here is sample Python 2 code for doing requests over the 1.1.1.1 DNS-over-HTTPS server.

#!/usr/bin/env python

NAME = "whatever.test.bamsoftware.com"

from scapy.all import *
import base64
import requests

# https://developers.cloudflare.com/1.1.1.1/dns-over-https/wireformat/#using-post
print("POST application/dns-udpwireformat")
udpwireformat = str(DNS(rd=True, qd=DNSQR(qtype="A", qname=NAME)))
r = requests.post("https://1.1.1.1/dns-query",
    headers = {
        "Accept": "application/dns-udpwireformat",
        "Content-Type": "application/dns-udpwireformat",
    },
    data = udpwireformat,
)
DNS(r.content).show()

# https://developers.cloudflare.com/1.1.1.1/dns-over-https/wireformat/#using-get
print("POST application/dns-udpwireformat")
udpwireformat = str(DNS(rd=True, qd=DNSQR(qtype="A", qname=NAME)))
r = requests.get("https://1.1.1.1/dns-query",
    params = {
        "dns": base64.urlsafe_b64encode(udpwireformat),
        "ct": "application/dns-udpwireformat",
    },
)
DNS(r.content).show()

# https://developers.cloudflare.com/1.1.1.1/dns-over-https/json-format/
print("GET application/dns-json")
r = requests.get("https://1.1.1.1/dns-query",
    params = {
        "name": NAME,
        "type": "A",
        "ct": "application/dns-json",
    },
)
print r.text

If you run this, you will see requests arrive at the broker and responses come back with rcode=server-failure, which is expected because there's nothing running at snowflake-broker.bamsoftware.com:53 yet.

comment:2 Changed 8 months ago by sysrqb

If it gains in popularity, DNS-over-TLS is another option. There are already quite a few providers[1], but I doubt any of them are sufficient for domain fronting at this point, although I see Cloudflare is now on the list.

[0] https://dnsprivacy.org/wiki/
[1] https://dnsprivacy.org/wiki/display/DP/DNS+Privacy+Test+Servers

comment:3 Changed 8 months ago by cypherpunks

Bulletproof transport. Joke, based on real life.

comment:4 Changed 7 months ago by cypherpunks

To be considered: rendezvous over dns makes enumeration easier.

Note: See TracTickets for help on using tickets.