Skip to content

jess-sys/dnschat

Repository files navigation

dnschat

A DNS-tunneled encrypted chat system. Uses the DNS protocol as a covert transport layer for end-to-end encrypted messages.

Why DNS? (Use Cases)

DNS is the "universal protocol" that is almost never blocked, even on the most restrictive networks. dnschat leverages this to provide connectivity where other tools fail:

  • Bypassing Captive Portals: Many public Wi-Fi networks (hotels, airports, coffee shops) block all traffic until you pay or sign in, but allow DNS queries to resolve. dnschat can tunnel through these restrictions.
  • Highly Restrictive Firewalls: In environments where only DNS (port 53) is permitted, dnschat provides a functional communication channel without requiring VPNs or complex proxies.
  • Covert Communication: Because the traffic looks like standard DNS queries for a specific domain, it can blend in with normal network noise more easily than direct TCP/IP connections.
  • No Direct IP Connectivity: Clients only need to reach a recursive DNS resolver (like 8.8.8.8 or their local gateway), not the dnschat server directly.

How it Works

  1. Transport: Messages are Base32-encoded and embedded into DNS TXT query labels (e.g., <chunk>.send.chat.example.com).
  2. Relay: A custom authoritative DNS server receives these queries, reassembles the chunks, and stores them in the recipient's "inbox" in memory.
  3. Security: Everything is End-to-End Encrypted (E2EE). The server is a blind relay—it only sees opaque encrypted blobs and never has access to your private keys or plaintext.
  4. Retrieval: The recipient polls their inbox via DNS queries and receives the encrypted blobs back as DNS TXT responses.

See SPEC.md for the full protocol specification (v0.3).

Server

The server is a custom authoritative DNS server that acts as a blind message relay. It never sees plaintext — all payloads are encrypted client-side.

Endpoints

Endpoint Purpose
register Publish a user's X25519 public key
bind Associate an email with a key ID
unbind Remove an email binding
lookup Find a public key by username
resolve Find a public key by email
send Submit an encrypted message (chunked)
inbox Retrieve pending messages
ack Acknowledge and delete a message

Running

# Default: listens on 0.0.0.0:5353, domain chat.example.com
python server.py

# Custom settings
python server.py --host 127.0.0.1 --port 5353 --domain chat.mydomain.com --debug

# All options
python server.py --help

No dependencies beyond Python 3.10+ standard library.

Testing

python -m unittest test_server -v

DNS Setup (production)

To use this in production, you need to delegate a subdomain to this server:

  1. Add an NS record: chat.example.com. NS ns-chat.example.com.
  2. Add a glue A record: ns-chat.example.com. A <your-server-ip>
  3. Run the server on port 53 (requires root): sudo python server.py --port 53 --domain chat.example.com

Architecture

┌─────────┐   DNS TXT query    ┌──────────────────┐
│  Client  │ ──────────────────▶│  dnschat server  │
│ (sender) │                    │                  │
└─────────┘   TXT "OK:c0fe:0"  │  ┌────────────┐  │
              ◀──────────────── │  │   Store     │  │
                                │  │ ┌─keys────┐ │  │
┌─────────┐   DNS TXT query     │  │ ┌─emails──┐ │  │
│  Client  │ ──────────────────▶│  │ ┌─inboxes─┐ │  │
│ (recvr)  │                    │  └────────────┘  │
└─────────┘   TXT "<msg_data>"  │                  │
              ◀──────────────── └──────────────────┘

Storage is in-memory. Restarting the server clears all state.

About

A DNS-tunneled encrypted chat system (proof of concept)

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors