Skip to content

About

One public port 53 in front of many DNS tunnels.

Resources

Security policy

Stars

184 stars

Watchers

0 watching

Forks

Latest commit

Β 

History

72 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

CottenRouter β€” One public gateway for multiple DNS tunnels

Fast, safe, and payload-transparent routing for DNS and TLS transports.

Release CI Go License Container

فارسی · CottenMax beta · Install · Usage · Commands · Docker · Upgrade · Uninstall · Credits


✨ Overview

CottenRouter is a lightweight front router that lets multiple DNS-tunnel backends share one server, one IP address, and public port 53. It reads the first DNS question, selects the longest matching configured suffix, and forwards the packet to the correct private backend.

It can also share public DoT and HTTPS ports by reading TLS SNI and passing each encrypted stream through unchanged. CottenRouter does not terminate TLS, add DNS labels, or add protocol bytes, so it does not reduce tunnel MTU.

Key features:

  • Concurrent routing for several DNS-tunnel projects on one public endpoint
  • UDP DNS, DNS-over-TCP, DoT, DoH, NaiveProxy, and StunTLS passthrough
  • Guided terminal UI for installation, configuration, monitoring, and removal
  • Transactional host installation with snapshots, health checks, and rollback
  • Fixed queues, rate limits, timeouts, connection caps, and resource controls
  • Loopback-only administration API and a dashboard refreshed every two seconds
  • Rootless, read-only, shell-free Docker image
  • Checksum-verified linux/amd64 and linux/arm64 release binaries

How traffic flows

flowchart LR
    C[DNS / TLS clients] -->|UDP/TCP 53, DoT, HTTPS| R[CottenRouter]
    R -->|Longest DNS suffix| D1[CottenDNS :5301]
    R -->|Longest DNS suffix| D2[MasterDnsVPN :5302]
    R -->|Longest DNS suffix| D3[StormDNS :5303]
    R -->|Longest DNS suffix| D4[thefeed :5304]
    R -->|Longest DNS suffix, UDP| D6[Soar :5305]
    R -->|Longest DNS suffix, UDP| D7[Soar 2.2 :5306]
    R -->|Longest DNS suffix, UDP/TCP| D8[WhiteDNS Panel :5307]
    R -->|DNS route or TLS SNI| D5[SlipGate services]
    R -.->|Loopback only| A[Admin API :9088]
Loading

Choose a deployment

Host installation Docker
Routing core βœ… βœ…
Guided backend installers βœ… β€”
Interactive control deck βœ… β€”
systemd and firewall integration βœ… β€”
Rootless runtime β€” βœ…
Best for A fresh server managed end to end Existing container infrastructure

WhiteDNS Panel and independent updates

WhiteDNS Panel is a separate Easy Install entry alongside Soar and Soar 2.2. The default installer resolves the newest published stable panel-v* release independently of the Router version, selects the Linux AMD64 or ARM64 bundle for the host, and verifies the archive and embedded runtime checksums. The current integration is tested with Panel v0.14.4.

sudo cottenrouter install --project whitedns-panel --domain p.example.com --tcp
sudo cottenrouter update --project whitedns-panel

Leave the TUI's Legacy beta archive field blank for the current stable release. The pinned Panel 0.5.1 CI archive remains available only through explicit --panel-beta-bundle selection; ordinary installs and updates do not choose it. Soar 2.2 remains the separate older standalone Lantern v0.2.2 option.

Use a separate, short delegated base zone for the Panel. Router forwards its account subdomains to the private backend. Current Panel accounts provide Soar, Cotten and MasterDNS with native per-engine settings. The standalone CottenDNS entry provides Normal and CottenMax with their existing shared domain/key.

Router imports the Panel's current serving zones on install, update, Configure and Advanced saves. After changing tunnel zones in the Panel, save its Router Configure form to refresh the routes. Preserve the existing identity base zone and private DNS port; serving zones may change without replacing account identities.

The first Panel install prompts for an administrator password; automated installs can pass --panel-password-file /path/to/protected-file (0600). Updates preserve the database, account keys, usage and chosen session limits. Router verifies archive/runtime checksums, the selected version and supported CLI contract, checks readiness, and restores the previous service and database if an upgrade fails.

Administration binds to loopback, normally 127.0.0.1:2054; occupied ports are skipped. Run sudo cottenrouter keys --project whitedns-panel to find the address, then forward it, for example ssh -L 2054:127.0.0.1:2054 root@SERVER. Router owns maintenance for this installation. Account management and backup downloads remain in the Panel; its standalone privileged updater and public HTTPS wizard are unavailable in Router mode.

For CottenDNS, use sudo cottenrouter update --project cottendns. Every operation resolves the latest published compatible release independently of Router's version, with no silent stale-version fallback.

Published standalone CottenDNS and CottenMax have no hidden eight-session cap: defaults are 2,048 sessions and expanded capacity raises them to at least 4,096. Panel uses the per-engine account limits and defaults provided by its selected release; Router preserves explicit administrator settings. These are session ceilings, not guaranteed user counts.

CottenMax beta

CottenMax is available for opt-in beta testing inside CottenDNS. It reuses the CottenDNS service, delegated domain, shared key and existing Router route. Select Normal / CottenMax beta in a compatible client; an updated CottenDNS server accepts both modes. No extra Router project, route or shared key is needed.

Component Beta availability
Router and CottenDNS source Changes are on main: TaJirax/CottenRouter, WhiteDNS/CottenDNS and TaJirax/cottenDNS
Desktop client Windows debug build, with Normal / CottenMax selection
Android client Debug APKs, with profile mode selection
Published installers Install the current CottenDNS release, supporting Normal and Max together

These CI artifacts are temporary and may require a GitHub sign-in. No new Desktop or Android release was published. Keep Normal mode available as a fallback while testing real devices, mobile networks and long-running connections.

The updated Max clients support UDP and TCP DNS for live tunnel traffic. Auto probes both paths independently during resolver discovery and authenticated MTU scanning, then carries traffic over usable paths. The existing local device proxy and Router route stay the same; see the UDP/TCP transport and scan guide.

For more session headroom, choose expanded in the CottenDNS form's Capacity field, or pass --expanded-capacity to its install/configure command. This opts in to at least 4096 server sessions, 1024 normal streams/session, and 512 Max streams/session; higher custom values are preserved. Max's higher cap requires updated server and clients. keep preserves current values. Rate and byte limits stay in force. These are configured ceilings, not a guaranteed user count; see capacity and limits.

Use the current Router release for the updated TUI and managed installer checks. Install or update the CottenDNS backend from the TUI or run sudo cottenrouter update --project cottendns; the operation independently resolves the latest published CottenDNS version. The app scanner shows live UDP/TCP paths, and Max connection state waits for authenticated transfer proof.

For an existing Router-managed backend, preserve its service working directory, configuration, key and private loopback listener ports when replacing its server binary. CottenRouter must retain public port 53; do not move the backend to that port. Reuse the existing CottenDNS route, then select Max in the client and reconnect. Very long legacy domains can exceed Max's domain limits.

The Router Guide tab and CottenDNS install form explain the shared domain/key and compatible-server requirement. See terminal setup and mode switching and optional Max transports and tuning. DoH over HTTP/3 and DoQ are client-to-resolver options; they do not add QUIC passthrough or authoritative QUIC listeners to CottenRouter.

Soar and Soar 2.2 remain separate backends with their own zones and keys. CottenMax is the mode inside CottenDNS; Soar 2.2 remains the older Lantern v0.2.2 option described below.


βœ… Requirements

For a host installation you need:

  • Linux with systemd 245+
  • root or sudo access
  • A public IP and at least one unique domain or subdomain for each backend
  • Ubuntu 20.04+, Debian 11+, or RHEL/Rocky/AlmaLinux 9+ is recommended
  • amd64 or arm64 for a prebuilt binary; other architectures build from source

WSL is supported for development and testing only. Use a native Linux server for production.


πŸš€ Installation

Latest stable release

curl -fsSL https://raw.githubusercontent.com/TaJirax/CottenRouter/main/scripts/install.sh | sudo bash
sudo cottenrouter tui

The installer downloads the latest official release, verifies its checksum, checks required tools, systemd, disk space, and listeners, and waits for a successful health check. A failed installation restores the previous state. Running the command again performs an in-place upgrade.

To install the current checkout, including local changes and all seven backends, run these commands from the repository root on Linux or inside WSL:

sudo bash scripts/install.sh --local-source="$PWD"
sudo cottenrouter tui

Open Install, select projects with Space, and press i for the guided queue. Tab moves fields; Enter on the last field installs. Each project needs its own delegated domain. Thefeed asks for at least one source in its native setup; SlipGate opens its native multi-tunnel wizard.

Install a specific release:

curl -fsSL https://raw.githubusercontent.com/TaJirax/CottenRouter/main/scripts/install.sh \
  | sudo bash -s -- --version=v1.2.26

Install the current development branch:

curl -fsSL https://raw.githubusercontent.com/TaJirax/CottenRouter/main/scripts/install.sh \
  | sudo bash -s -- --channel=edge

Build from source during installation:

curl -fsSL https://raw.githubusercontent.com/TaJirax/CottenRouter/main/scripts/install.sh \
  | sudo bash -s -- --build-from-source
Installer option Purpose
--version=vX.Y.Z Install an exact tagged release
--channel=stable Install the latest release; this is the default
--channel=edge Build the latest default-branch commit for testing
--build-from-source Compile locally instead of using a release binary
--no-swap Skip the installer-owned emergency swap safeguard

🧭 Control deck

sudo cottenrouter tui
Key Action
Tab / Shift+Tab Switch Overview, Install, Ports and Guide tabs
Space Select or deselect a project
i Run guided installation for selected projects
Enter / e Edit domains, private ports, TCP, DoT, and DoH
a Open the complete native project configuration
s Restart a project
U Update an installed backend from its published channel
u Detach a project while preserving its files
x Permanently remove a project after confirmation
v Show credential paths and public values
V Reveal secrets after explicit confirmation

Give every backend a unique delegated domain, for example cotten.example.com, master.example.com, storm.example.com, feed.example.com, and soar.example.com. Exact duplicate suffixes are rejected. Nested suffixes are supported and the longest match wins.

Soar

Select Soar in the project manager, or install it directly:

sudo cottenrouter install --project=soar --domain=soar.example.com
sudo cottenrouter keys --project=soar

Soar builds the latest resolved official Lantern commit, provisions a compatible Go toolchain when needed, and creates soar-server on UDP 127.0.0.1:5305. Source builds need network access for Go and module downloads plus disk space for the compiler and build cache.

Soar 2.2 is a separate option using WhiteDNS's standalone setup 0.1.3 bundle with the older Lantern engine v0.2.2. It downloads a checksum-verified prebuilt amd64 binary and runs soar22-server on UDP 127.0.0.1:5306:

sudo cottenrouter install --project=soar22 --domain=soar22.example.com
sudo cottenrouter keys --project=soar22

Both options can run together with separate delegated zones, ports, and keys. CottenRouter manages their services; WhiteDNS's native wizard, manager, and web panel are not run. Each option uses one delegated zone; backend TCP, DoT, DoH, extra domains, and chat domains are unavailable. Share each displayed public key with its clients; private seeds stay on disk and survive reinstallation. See Soar setup for configuration and verification.


πŸ“Š Status and configuration

sudo systemctl status cottenrouter
sudo journalctl -u cottenrouter -f
sudo cottenrouter healthz -config /etc/cottenrouter/config.json
curl -fsS http://127.0.0.1:9088/v1/status

Validate or run a configuration manually:

cottenrouter check -config cottenrouter.json
cottenrouter serve -config cottenrouter.json

Start with cottenrouter.example.json, or use cottenrouter.docker.json for containers. Unknown configuration fields are rejected.

Import an existing SlipGate configuration:

cottenrouter slipgate-import \
  --input /etc/slipgate/config.json \
  --output cottenrouter.json

SlipGate DNS transports, including Soar, support both UDP and TCP ingress; imported routes use tcp_backend: "udp" to reach their native UDP listeners. Feed's native main, alias, messenger and MTProto domains are automatically routed together on install, update and Advanced save. See backend integration for native paths and settings.

Inspect current upstream projects and installers:

cottenrouter catalog
cottenrouter catalog --offline

The online catalog resolves and verifies each project's current default branch. The offline output is bundled fallback metadata and is not recommended for installation.


πŸ“š Command reference

cottenrouter tui               Install, manage, and monitor projects
cottenrouter serve             Run the router with a configuration
cottenrouter check             Validate a configuration without serving
cottenrouter healthz           Probe router health
cottenrouter install           Install a backend from the CLI
cottenrouter update            Update an installed backend independently
cottenrouter configure         Edit stable backend settings
cottenrouter advanced          Edit advanced native backend settings
cottenrouter service           Start, stop, or restart a project
cottenrouter remove            Detach or purge a project
cottenrouter uninstall         Alias for the project removal operation
cottenrouter keys              Display project credentials
cottenrouter catalog           List current projects and installers
cottenrouter slipgate-import   Convert an existing SlipGate configuration
cottenrouter version           Print the installed version

Use cottenrouter <command> --help for command-specific options.

Manage a service directly:

sudo cottenrouter service --project=cottendns --action=restart
sudo cottenrouter service --project=stormdns --action=stop
sudo cottenrouter service --project=stormdns --action=start

Detach one backend while preserving its files:

sudo cottenrouter remove --project=cottendns

Permanently remove that backend's managed data:

sudo cottenrouter remove --project=cottendns --purge --confirm=cottendns

🐳 Docker

The container runs the routing core only. You remain responsible for the lifecycle of backend containers.

curl -fsSLO https://raw.githubusercontent.com/TaJirax/CottenRouter/main/docker-compose.yml
curl -fsSLO https://raw.githubusercontent.com/TaJirax/CottenRouter/main/cottenrouter.docker.json

# Replace the example domain and backend in cottenrouter.docker.json
docker compose up -d

Check health:

docker compose exec cottenrouter \
  /usr/local/bin/cottenrouter healthz \
  -config /etc/cottenrouter/config.json

Update or remove the container:

docker compose pull
docker compose up -d
docker compose down

The official ghcr.io/tajirax/cottenrouter image supports linux/amd64 and linux/arm64. It listens on unprivileged port 5353 inside the container while Docker publishes host port 53. It runs as UID 65532, drops all capabilities, uses a read-only root filesystem, and includes no shell. See the Docker guide.


πŸ”„ Upgrade

The installer upgrades CottenRouter in place. It snapshots the active configuration, replaces the binary, validates the configuration, restarts the service, and waits for the health probe. If any step fails, it restores the previous installation automatically.

flowchart LR
    A[Current installation] --> B[Snapshot config and service state]
    B --> C[Download and verify release]
    C --> D[Validate and restart]
    D -->|Health check passes| E[Upgrade complete]
    D -->|Health check fails| F[Automatic rollback]
Loading

Upgrade to the latest stable release

curl -fsSL https://raw.githubusercontent.com/TaJirax/CottenRouter/main/scripts/install.sh | sudo bash

Upgrade or downgrade to an exact release

Pinning a version is useful for reproducible deployments or returning to a known release:

curl -fsSL https://raw.githubusercontent.com/TaJirax/CottenRouter/main/scripts/install.sh \
  | sudo bash -s -- --version=v1.2.26

Available versions are listed on the Releases page.

Upgrade to the development channel

Use this only when you intentionally want the latest default-branch commit:

curl -fsSL https://raw.githubusercontent.com/TaJirax/CottenRouter/main/scripts/install.sh \
  | sudo bash -s -- --channel=edge

Upgrade Docker

docker compose pull
docker compose up -d

The configuration is a read-only bind mount, so replacing the container does not replace your local config file.

Verify the upgrade

Backend updates are independent of CottenRouter updates:

sudo cottenrouter update --project cottendns

In the TUI, select an installed project and press U. CottenDNS resolves the latest published WhiteDNS release on every operation and checks the installed binary version. Domains, keys and routing settings are preserved.

This is the published-release path. If you installed the CottenMax source beta, use its beta update workflow to retain Max support; a backend update can replace a beta binary with the latest published release.

cottenrouter version
sudo systemctl --no-pager --full status cottenrouter
sudo cottenrouter healthz -config /etc/cottenrouter/config.json

Production tip: use the stable channel or an exact version. Take a server snapshot before upgrading upstream backend projects, because their native installers run as root and are maintained independently.


πŸ—‘οΈ Uninstall

Safely remove CottenRouter while preserving configuration, upstream projects, panels, pre-existing firewall rules, and swap:

sudo cottenrouter-uninstall

Also delete the router configuration:

sudo cottenrouter-uninstall --purge --confirm CottenRouter

Delete CottenRouter, every managed backend, and their managed data:

sudo cottenrouter-uninstall \
  --purge \
  --purge-backends \
  --confirm CottenRouter

Remove only swap created and marked as owned by the installer:

sudo cottenrouter-uninstall --remove-swap --confirm CottenRouter

Purge operations cannot be undone. CottenRouter removes only firewall rules, accounts, and swap carrying its ownership markers; it does not remove pre-existing state.


πŸ›‘οΈ Routing and security model

  1. Parse the first DNS question and drop malformed packets.
  2. Select the longest configured domain suffix.
  3. Allocate a transaction ID on a connected backend socket.
  4. Forward the packet unchanged apart from that temporary ID.
  5. Accept a reply only when its question name, type, and class match exactly.
  6. Restore the client's original ID and return the reply.

IDs are never reused in one socket generation. After all 65,536 IDs have been consumed, CottenRouter rotates to a new source port so a late response cannot enter the new generation.

Remote backends are rejected by default, both UDP and TCP messages are capped at 16 KiB, and the admin API must remain on loopback. Transaction-ID and question matching is not cryptographic authentication; configured backends are trusted. Host backend installers run as root, so snapshot the server before running an upstream release you have not reviewed.

Read more in Security, Installer and control deck, and Backend integration.


πŸ› οΈ Build, test, and contribute

git clone https://github.com/TaJirax/CottenRouter.git
cd CottenRouter
go build -o cottenrouter ./cmd/cottenrouter

go test ./...
go test -race ./...
go vet ./...
gofmt -w cmd internal

CI also checks backend isolation under load, full 16 KiB packets, throughput, concurrent DoT/DoH and NaiveProxy/StunTLS routing, formatting, and the rootless Docker image.

Use Issues for bugs and feature requests, and Pull Requests for code contributions.

Documentation

Guide Contents
Docker Rootless container layout, networking, images, and updates
Installer and control deck TUI controls, ports, panels, safeguards, and removal
Backend integration Domains, listeners, feature boundaries, and project notes
Soar setup Official Soar and WhiteDNS's older Soar 2.2 option, routing, keys, and verification
CottenMax beta Client debug builds, compatible server requirement, shared credentials and release-channel status
Security Flood controls, resource limits, systemd hardening, and swap
Configuration example Complete annotated-style configuration starting point
Release notes v1.2.13 What changed since v1.2.10, upgrade steps, and load-test results

🀝 Projects and credits

CottenRouter is designed to interoperate with these independent open-source projects. We sincerely thank their authors and contributors:

Project Role in the ecosystem Link
CottenDNS DNS tunnel with UDP/TCP, DoT, DoH, ARQ, MTU discovery and the optional CottenMax beta mode Repository
MasterDnsVPN DNS tunneling backend Repository
StormDNS DNS tunneling backend Repository
thefeed Feed, chat, MTProto, media, and relay over DNS Repository
Soar Encrypted TCP streams through recursive DNS resolvers Repository
Soar 2.2 / WhiteDNS Standalone bundle of Lantern Soar v0.2.2 Repository
SlipGate DNS transports including Soar, SlipNet, NaiveProxy, and StunTLS Repository

The terminal UI is built with Bubble Tea, Bubbles, and Lip Gloss from Charm. The Docker runtime uses scratch with the static router and trusted CA certificates. Complete dependency lists are available in go.mod and go.sum.

No upstream source tree or binary is vendored in this repository. Every upstream project retains its own copyright and license, and its installer is fetched directly from its repository only when requested by the operator. See NOTICE.md.


πŸ“„ License

CottenRouter is released under the MIT License. Upstream integrations remain subject to their respective project licenses.

Built for cleaner, safer, and more manageable DNS-tunnel deployments.

Back to top · فارسی

About

One public port 53 in front of many DNS tunnels.

Resources

Security policy

Stars

184 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages