DNS Tunnel Client (dnstc)
March 1, 2026 · View on GitHub
A cross-platform CLI tool for managing DNS tunnel connections. Supports multiple transport and backend types with both interactive TUI and CLI interfaces.
Features
- Transports: Slipstream and DNSTT
- Backends: SOCKS, SSH (dynamic forwarding), and Shadowsocks (SIP003 plugin)
- Import: Import tunnel configs from
dnstm://URLs generated by dnstm'stunnel share - Gateway proxy: Single SOCKS port routing to the active tunnel, switchable at runtime
- Daemon: Systemd-managed daemon on Linux (
dnstc daemon enable+dnstc daemon start) - Interactive TUI: Status viewer with tunnel management and configuration
- Binary management: Install, update, and self-update via
dnstc installanddnstc update - Named tunnels: Auto-generated adjective-noun tags (e.g.
swift-tunnel) - Per-tunnel ports: Each tunnel gets its own local port, auto-assigned if not specified
Installation
go install github.com/net2share/dnstc@latest
Or build from source:
git clone https://github.com/net2share/dnstc.git
cd dnstc
go build -o dnstc .
Transport + Backend Combinations
| Transport | Backend | Description | Required Config |
|---|---|---|---|
| slipstream | shadowsocks | Slipstream as Shadowsocks SIP003 plugin | domain, ss-server, ss-password |
| slipstream | socks | Slipstream standalone SOCKS proxy | domain |
| slipstream | ssh | SSH dynamic forwarding over Slipstream | domain, ssh-user, ssh-password/key |
| dnstt | socks | DNSTT standalone SOCKS proxy | domain, pubkey (64-char hex) |
| dnstt | ssh | SSH dynamic forwarding over DNSTT | domain, pubkey, ssh-user, ssh-password/key |
Note:
dnstt + shadowsocksis not a supported combination.
Usage
Interactive TUI
Run without arguments:
dnstc
Interactive menu with tunnel management, configuration, and live service status. The TUI auto-detects when a daemon starts or stops in another terminal.
Daemon Management
The daemon runs via systemd on Linux. First enable the service, then start it:
sudo dnstc daemon enable # Install and enable systemd service (once)
dnstc daemon start # Start service and tunnels
dnstc daemon stop # Stop service (IPC graceful shutdown)
dnstc daemon status # Show daemon and tunnel status
sudo dnstc daemon disable # Stop and remove systemd service
Tunnels auto-start when the service starts (including after reboot). Config changes via CLI (tunnel add, tunnel remove, config edit, etc.) are automatically picked up by the running daemon.
Logs are available via journalctl -u dnstc.
CLI Commands
Install & Update
dnstc install # Download and install required binaries
dnstc update # Check and apply updates (binaries + self)
dnstc update --check # Check only, don't apply
dnstc update --self # Update dnstc only
dnstc update --binaries # Update binaries only
Tunnel Management
# Import a tunnel from a dnstm:// URL (generated by dnstm tunnel share)
dnstc tunnel import dnstm://...
# Add a tunnel manually
dnstc tunnel add --transport slipstream --backend socks -d tunnel.example.com
dnstc tunnel add --transport dnstt --backend socks -d tunnel.example.com --pubkey <64-char-hex>
dnstc tunnel add --transport slipstream --backend shadowsocks -d tunnel.example.com \
--ss-server 127.0.0.1:8388 --ss-password secret
dnstc tunnel add --transport slipstream --backend ssh -d tunnel.example.com \
--ssh-user tunnel --ssh-password secret
# Add with a specific local port (auto-assigned if omitted)
dnstc tunnel add --transport slipstream --backend socks -d tunnel.example.com -p 9050
# List tunnels
dnstc tunnel list
# Show tunnel status
dnstc tunnel status -t <tag>
# Switch active tunnel (gateway routes to this tunnel)
dnstc tunnel activate -t <tag>
# Remove a tunnel
dnstc tunnel remove -t <tag> --force
Configuration
dnstc config show # Display current config
dnstc config edit # Open config in $EDITOR
dnstc config gateway-port -p 1080 # Set gateway proxy port
Uninstall
dnstc uninstall --force
Removes config, state, downloaded binaries, and systemd service.
Architecture
┌──────────────────────────┐
│ Gateway │ Single port (default :1080)
│ SOCKS proxy entry │ Accepts client connections
└───────────┬──────────────┘
│ routes to active tunnel
▼
┌──────────────────────────┐
│ Active Tunnel │ Per-tunnel local port
│ (e.g. :41023) │ Running transport binary
└───────────┬──────────────┘
│ DNS queries → configured resolver
▼
Remote Server
- The gateway is a TCP relay that listens on a single configurable port and forwards each connection to whichever tunnel is currently active.
- Switching the active tunnel takes effect on the next connection — no restart needed.
- Each tunnel runs as a child process (slipstream-client, dnstt-client, or sslocal) on its own local port. SSH backend tunnels additionally run an in-process SSH client with SOCKS5 dynamic forwarding.
- DNS queries are sent directly to the configured resolver (default
1.1.1.1:53), avoiding any proxy-level reconstruction that could break tunnel protocols.
Configuration
Stored in ~/.config/dnstc/config.json:
{
"listen": {
"socks": "127.0.0.1:1080"
},
"resolvers": ["1.1.1.1:53"],
"tunnels": [
{
"tag": "swift-tunnel",
"transport": "slipstream",
"backend": "shadowsocks",
"domain": "tunnel.example.com",
"port": 41023,
"shadowsocks": {
"server": "127.0.0.1:8388",
"password": "your-password",
"method": "chacha20-ietf-poly1305"
}
},
{
"tag": "cool-proxy",
"transport": "dnstt",
"backend": "socks",
"domain": "dns.example.com",
"port": 41024,
"dnstt": {
"pubkey": "0123456789abcdef..."
}
},
{
"tag": "ssh-tunnel",
"transport": "slipstream",
"backend": "ssh",
"domain": "tunnel.example.com",
"port": 41025,
"ssh": {
"user": "tunnel",
"password": "secret"
}
}
],
"route": {
"active": "swift-tunnel"
}
}
listen.socks— Gateway port. Auto-assigned if the default (1080) is unavailable.resolvers— DNS resolvers used by tunnels (default1.1.1.1:53). First entry is used.tunnels[].port— Per-tunnel local SOCKS port. Auto-assigned when adding a tunnel.tunnels[].resolver— Per-tunnel DNS resolver override.route.active— Tag of the tunnel the gateway routes to.
File Locations
| Purpose | Path |
|---|---|
| Configuration | ~/.config/dnstc/config.json |
| Versions | ~/.config/dnstc/versions.json |
| Process state | ~/.config/dnstc/state.json |
| IPC Socket | ~/.config/dnstc/engine.sock |
| Binaries | ~/.local/share/dnstc/bin/ |
| Daemon logs | journalctl -u dnstc |
Automatic migration from YAML config (config.yaml) to JSON is performed on first run.
Related Projects
- dnstm — DNS Tunnel Manager (server-side)
- go-corelib — Shared Go library