A lightweight DNS proxy designed to bypass DNS spoofing by exploiting timing differences between fake and legitimate packets
Project description
LatterDNS
LatterDNS is a lightweight, experimental DNS proxy designed to bypass DNS spoofing; a common censorship method used by the Great Firewall (GFW); by exploiting the timing difference between fake and legitimate packets.
"The truth arrives late."
How It Works
This tool operates on a simple observation: Censorship is a race.
-
The Trigger: When you query a blocked domain (e.g.,
facebook.com), the firewall detects the request. -
The Race: The firewall attempts to "poison" your DNS cache by racing to send you a fake response (usually a random or reset IP) before the legitimate DNS server can respond.
-
The Exploit: Because the firewall is injecting packets locally/en route, the fake response almost always arrives first. The legitimate response from the real DNS server travels a longer path and arrives second (milliseconds later).
LatterDNS simply discards the first response it sees for every query and accepts the second one.
Visualizing the Logic
sequenceDiagram
participant Client
participant LatterDNS
participant GFW
participant RealDNS
Client->>LatterDNS: Query: facebook.com
LatterDNS->>RealDNS: Forward Query
Note over GFW: GFW detects keyword!
GFW-->>LatterDNS: Fake IP (First Packet)
Note over LatterDNS: 🛑 BLOCKED (Too fast)
RealDNS-->>LatterDNS: Real IP (Second Packet)
Note over LatterDNS: ✅ ACCEPTED (The Latter)
LatterDNS->>Client: Real IP
Installation
Normal Usage
pip install latterdns
Development
git clone https://github.com/itsamirhn/latterdns.git
cd latterdns
uv pip install -e .
Usage
Once installed, you can run LatterDNS from anywhere using the latterdns command.
# Basic usage (defaults to listening on port 1053)
latterdns
# Custom upstream (Google DNS) and stricter timeouts
latterdns --upstream-host 8.8.8.8 --latter-timeout 0.15
# Enable debug logging
latterdns --log-level DEBUG
Available Options:
You can view all options anytime by running latterdns --help:
Usage: latterdns [OPTIONS]
LatterDNS - Returns the latter DNS response packet from upstream.
Options:
--listen-port INTEGER Port to listen on [default: 1053]
--upstream-host TEXT Upstream DNS host [default: 1.1.1.1]
--upstream-port INTEGER Upstream DNS port [default: 53]
--former-timeout FLOAT Timeout for former packet [default: 1.0]
--latter-timeout FLOAT Timeout for latter packet [default: 0.5]
--log-level [DEBUG|INFO|WARNING|ERROR|CRITICAL]
Logging level [default: INFO]
--help Show this message and exit.
🧪 How to Test
To verify that LatterDNS is working, you need to query a domain known to be poisoned by the GFW.
1. Without LatterDNS (The Control Test) Run a query against a standard upstream DNS. You should see a suspicious IP (often changed) or a connection reset.
dig @8.8.8.8 facebook.com +short
# Result: 1.2.3.4 (Fake IP / Poisoned Result)
2. With LatterDNS Point your query to the local port where LatterDNS is running (e.g., 1053).
dig @127.0.0.1 -p 1053 facebook.com +short
# Result: 157.240.x.x (Real Facebook IP)
⚠️ Limitations & Trade-offs
-
Latency for Unblocked Domains: For unblocked domains (where the GFW sends nothing), the proxy receives the legitimate packet first. It must wait
latter-timeout(default 0.1s) to ensure no other packet is coming before returning the result. This adds ~100ms latency to every unblocked query. -
Packet Loss: If the legitimate packet (the second one) is lost in transit, the proxy will timeout and return the first packet (the fake one), failing to bypass the block.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file latterdns-0.2.0.tar.gz.
File metadata
- Download URL: latterdns-0.2.0.tar.gz
- Upload date:
- Size: 5.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.13 {"installer":{"name":"uv","version":"0.9.13"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d8769deeef73b90d0d466171cb1e3e5beeea0710628cdee02366de042f315c49
|
|
| MD5 |
84d67a8c96e738ed79307a17cbe993b3
|
|
| BLAKE2b-256 |
999658be1bbc4a17caefd1a0342e9334d5a17e10a662ff016030c58835d0a993
|
File details
Details for the file latterdns-0.2.0-py3-none-any.whl.
File metadata
- Download URL: latterdns-0.2.0-py3-none-any.whl
- Upload date:
- Size: 5.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.13 {"installer":{"name":"uv","version":"0.9.13"},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
97aa31002cb8e497256fbe0b5e0339dc64ceefa281a533f7a94f5e481099037a
|
|
| MD5 |
45d4cbf0c4dbd8db9809bc4f23708b22
|
|
| BLAKE2b-256 |
ac8a6d348a9400d1f3470799734c7ed5d5d89bbb07cd59fd7c70bc40f0ab2cd1
|