When standard network ports are blocked by restrictive firewalls or corporate proxy policies, DNS queries often remain the one channel left open. DNS tunneling exploits this reality by encoding arbitrary network traffic inside DNS queries and responses. This guide compares the two most established open-source DNS tunnel implementations — iodine and dnscat2 — and helps you choose the right tool for your environment.
Why Self-Host a DNS Tunnel
DNS tunneling serves several legitimate operational purposes for network administrators and infrastructure engineers:
- Remote server access during outages — When primary VPN or SSH connectivity fails due to network issues, a DNS tunnel provides a reliable fallback channel for emergency administration.
- Firewall bypass in restrictive environments — Some hosting providers or institutional networks block outbound SSH, HTTPS, or custom ports but allow DNS. A DNS tunnel can bridge the gap when no other option exists.
- Penetration testing and security auditing — Security teams use DNS tunnels during authorized engagements to test whether an organization’s network perimeter properly inspects and filters DNS traffic.
- Disaster recovery communication — When all other network infrastructure is compromised, DNS-based communication can serve as an out-of-band channel for coordination and data retrieval.
For related reading on complementary networking tools, see our guides on self-hosted tunnel alternatives to ngrok and WireGuard-based VPN solutions.
How DNS Tunneling Works
DNS tunneling operates by encoding data payloads inside DNS query names and responses. The process works as follows:
- Client encodes data — The client splits outgoing data into chunks and encodes them as DNS subdomain labels (e.g.,
aGVsbG8.dns-tunnel.example.com). - DNS resolver forwards — The local DNS resolver receives the query and forwards it through the standard DNS hierarchy to the authoritative nameserver for
dns-tunnel.example.com. - Server decodes and responds — Your authoritative DNS server (running the DNS tunnel software) receives the query, decodes the data, and encodes its response inside the DNS answer record.
- Bidirectional channel — This exchange repeats continuously, creating a bidirectional data channel that traverses any network allowing DNS resolution.
Because DNS is UDP-based by default (with TCP fallback for large responses), DNS tunnels can achieve reasonable throughput — typically 100 Kbps to 2 Mbps depending on encoding and network conditions.
Feature Comparison: iodine vs dnscat2
| Feature | iodine | dnscat2 |
|---|---|---|
| Primary purpose | General-purpose IPv4 tunnel | Command-and-control channel |
| Language | C (client and server) | C (client), Ruby (server) |
| Encryption | Optional password-based | Built-in (encrypted by default) |
| Protocol | Custom UDP-based | Custom with DNS fallback |
| Max throughput | ~2 Mbps (raw mode) | ~500 Kbps (conservative) |
| TCP tunneling | Full TUN/TAP (all protocols) | Limited (shell + file transfer) |
| Docker support | Community images | Community images |
| GitHub stars | 7,821 | 3,873 |
| Last update | September 2025 | March 2024 |
| Multi-client | Yes (multiple simultaneous clients) | Yes (multiple sessions) |
| Direct mode | No (requires authoritative DNS) | Yes (direct UDP/TCP to server) |
| Cross-platform client | Linux, macOS, Windows, Android, iOS | Linux, macOS, Windows |
| License | ISC | BSD |
iodine: General-Purpose DNS Tunnel
iodine is the most widely known DNS tunnel implementation. Written entirely in C, it creates a full TUN/TAP virtual network interface, allowing you to route all IPv4 traffic through the DNS channel — not just shell sessions.
Key Features
Full network tunneling. iodine creates a virtual network interface on both client and server. Once connected, the client can reach any server-side network resource — web servers, databases, internal APIs — as if directly connected to the remote network.
Adaptive encoding. iodine automatically selects the optimal DNS record type (TXT, NULL, SRV, CNAME, MX) based on what the upstream DNS resolver allows. It dynamically adjusts chunk sizes to maximize throughput within the constraints of each DNS server along the path.
Compression. Built-in zlib compression reduces data volume before encoding, improving effective throughput by 30-50% on compressible traffic.
Lightweight server. The iodine server (iodined) is a single compiled binary with minimal dependencies. It runs on any Linux system and requires no runtime environment.
Installation
From source (server and client):
| |
Ubuntu/Debian:
| |
Alpine Linux:
| |
Docker Deployment
Here is a production-oriented Docker Compose configuration for the iodine server:
| |
Server Configuration
The most important setup step is configuring your domain’s DNS to delegate a subdomain to your iodine server. If you run BIND:
| |
Start the server:
| |
The -c flag enables open mode (accepts connections from any client IP), and -f keeps it in the foreground. For production, remove -f and use a process manager.
Client Connection
| |
Once connected, the client receives IP 192.168.99.2 and can reach the server at 192.168.99.1. Route additional traffic through the tunnel:
| |
Performance Tuning
| |
Typical throughput on a residential connection ranges from 200 Kbps to 1.5 Mbps. Enterprise networks with fast DNS resolvers may achieve up to 2 Mbps.
dnscat2: Command-and-Control DNS Tunnel
dnscat2 takes a different approach. Instead of creating a full network tunnel, it establishes encrypted command channels optimized for interactive shell access and file transfer over DNS.
Key Features
Encrypted by default. Unlike iodine (where encryption is optional), dnscat2 encrypts all traffic between client and server using a pre-shared public key. This prevents passive observers from reading tunneled data even if they can decode the DNS queries.
Multi-session management. The dnscat2 server provides an interactive console where you can manage multiple connected clients, switch between sessions, spawn new shells, and transfer files — all through a single server instance.
Direct mode. dnscat2 can connect directly to the server on UDP port 53 without requiring an authoritative DNS server. This simplifies deployment when you don’t control a domain’s DNS records, though it’s more easily detected since all queries go to a single IP.
Ruby-based server. The server component runs on Ruby with gem dependencies, making it more flexible but also more resource-intensive than iodine’s C binary.
Installation
Server (Ruby required):
| |
Client (C, cross-compile for target platforms):
| |
Ubuntu/Debian (server):
| |
Docker Deployment
| |
Server Configuration
DNS delegation is similar to iodine — you need an NS record pointing to your server:
| |
Start the server:
| |
The --security=open flag allows any client to connect without pre-authentication. For production use, configure specific client IDs.
Client Connection
| |
Or using direct mode (no authoritative DNS required):
| |
Server Console
Once clients connect, you get an interactive management console:
| |
The console supports creating new shell sessions, uploading/downloading files, and managing multiple connected clients simultaneously.
Performance and Throughput Comparison
| Metric | iodine | dnscat2 |
|---|---|---|
| Peak throughput | 1.5–2 Mbps | 300–500 Kbps |
| Latency (ping through tunnel) | 50–200 ms | 100–400 ms |
| CPU usage (server) | Low (~2%) | Moderate (~8%) |
| Memory usage (server) | ~5 MB | ~50 MB (Ruby runtime) |
| Best use case | Full network access | Interactive shell + file transfer |
| TCP overhead | Minimal (raw IP tunnel) | Higher (application-layer tunnel) |
iodine consistently outperforms dnscat2 in raw throughput because it operates at the network layer (TUN/TAP) with efficient binary encoding. dnscat2 trades throughput for security and interactive features — every byte is encrypted and processed through the Ruby runtime.
Security Considerations
Encryption. dnscat2 encrypts all traffic by default using a Diffie-Hellman key exchange. iodine offers optional password authentication but does not encrypt tunneled data. If confidentiality matters, run iodine inside an SSH tunnel or use dnscat2.
Detection. Both tools generate unusually high volumes of DNS queries with long subdomain labels. Modern DNS security solutions (DNS-layer firewalls, anomaly detection systems) can flag this traffic. For authorized testing, establish baseline patterns and coordinate with network operations.
Access control. Both tools support password/secret-based authentication. dnscat2 additionally supports public-key client authentication. Neither tool provides built-in rate limiting — deploy a DNS firewall in front of the server for production use.
For organizations building comprehensive DNS security infrastructure, combining a DNS tunnel with DNS-over-HTTPS resolvers and DNS filtering tools creates layered defense and controlled access.
Which One Should You Choose?
Choose iodine if:
- You need full network-layer tunneling (access any IP/service on the remote network)
- Maximum throughput is important
- You want a minimal server footprint (single C binary, ~5 MB memory)
- You’re comfortable managing DNS delegation records
- You plan to route general traffic (HTTP, database connections, etc.) through the tunnel
Choose dnscat2 if:
- You primarily need interactive shell access to remote systems
- Built-in encryption is a requirement
- You need to manage multiple connected clients from a single console
- Direct mode (no DNS delegation) is acceptable for your use case
- File transfer through the tunnel is a regular requirement
For most remote administration scenarios, dnscat2 provides the better operator experience with its encrypted sessions and multi-client console. For full network access where you need to reach internal services beyond just a shell, iodine is the clear choice.
FAQ
Is DNS tunneling legal to use?
DNS tunneling is a networking technique — its legality depends on how you use it. Using DNS tunnels on networks you own or have explicit authorization to access is perfectly legal. Using them to bypass network restrictions on networks you don’t own (corporate networks, school networks, etc.) without permission may violate terms of service or local laws. Always ensure you have proper authorization.
Can DNS tunnels replace a VPN?
DNS tunnels can serve as a fallback when standard VPN connections fail, but they should not replace a VPN for regular use. DNS tunnels have significantly lower throughput (typically 1-2 Mbps maximum vs. 50-500 Mbps for WireGuard/OpenVPN), higher latency, and are more easily detected. Use them as an emergency access channel, not a primary connection.
How do I detect DNS tunneling on my network?
Look for: unusually long DNS query names (50+ characters in subdomains), high query volume from a single client (hundreds of queries per minute), queries for uncommon record types (TXT, NULL, SRV), and consistent query patterns to the same domain. DNS security tools like Pi-hole, Unbound, or dedicated DNS firewalls can monitor and alert on these patterns.
Does dnscat2 work over IPv6?
The dnscat2 client and server support IPv6 DNS queries, but the tunneled data itself is protocol-agnostic. The iodine project has limited IPv6 support through its TUN/TAP interface, but it primarily tunnels IPv4 traffic. For full IPv6 tunneling needs, consider dedicated IPv6-capable VPN solutions.
What DNS record types do these tools use?
iodine automatically selects the best available record type (TXT, NULL, SRV, CNAME, or MX) based on what the upstream DNS resolver permits. dnscat2 primarily uses TXT records for data transport. Both tools fall back to standard A/AAAA record queries when needed, though with reduced throughput.
Can I run iodine or dnscat2 alongside an existing DNS server?
Yes, but you cannot have two processes listening on port 53 simultaneously. Run your existing DNS server (BIND, Unbound, etc.) on a different port and use the DNS tunnel’s built-in forwarding, or configure your DNS server to forward queries for the tunnel subdomain to the tunnel software running on a separate port. The recommended approach is to run the DNS tunnel on port 53 and configure your primary DNS server to listen on a different port (e.g., 5353).
What is the maximum number of concurrent clients?
Both tools support multiple simultaneous client connections. iodine handles each client as a separate tunnel interface with its own IP address within the virtual network. dnscat2 manages multiple clients through its session console. Practical limits depend on server resources and DNS query capacity — expect 10-50 concurrent clients before DNS amplification becomes a concern.