# krot **Repository Path**: asd2015/krot ## Basic Information - **Project Name**: krot - **Description**: No description available - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-07-31 - **Last Updated**: 2026-07-31 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README

krot — tunnels that dig

CI Latest release License Rust stable

English · Русский

# krot **Self-hosted ngrok in Rust. Zero-knowledge, thread-per-core, passwordless.** `krot` is an open-source tunneling service: your own VPS, one Docker container, no subscription and no trust in a third-party relay. HTTPS traffic passes through the server encrypted end-to-end to the tunnel client, authorization keys are SSH-style (`authorized_keys`), and the apex-domain certificate is obtained and renewed by the server itself via ACME. Written in stable Rust on top of `tokio`, `quinn` (QUIC) and `rustls`. A single binary (~7 MB, release + LTO + strip), Docker image ~85 MB on debian-slim.
Table of contents - [What's inside](#whats-inside) - [Installation](#installation) - [Quick start](#quick-start) - [CLI reference](#cli-reference) - [Admin API](#admin-api) - [Architecture](#architecture) - [Federated relays](#federated-relays) - [Security](#security) - [Known limitations](#known-limitations) - [Development](#development) - [Contributing](#contributing) - [Reporting security issues](#reporting-security-issues) - [License](#license)
--- ## What's inside | | | |---|---| | **QUIC + TCP fallback** | Primary transport is QUIC over UDP. Clients behind corporate NATs that block UDP transparently fall back to TLS 1.3 over TCP with a mini-mux. Same port, distinguished by ALPN. | | **Zero-knowledge apex TLS** | The server terminates TLS **only** on the apex (`krot.example`). Connections to `alice.krot.example` go via SNI-passthrough — the server sees only an encrypted stream. Subdomain private keys never touch the server. | | **Thread-per-core** | Every core gets an isolated `tokio` current-thread runtime and its own QUIC endpoint via `SO_REUSEPORT`. Rate limits are partitioned per-core — each worker has its own bandwidth bucket, the aggregate cap is respected. | | **Passwordless Ed25519 bootstrap** | The client generates an Ed25519 key and knocks with a one-shot admin token (32 bytes of entropy, BLAKE3-hashed on disk, 10-minute TTL). The server appends the pubkey to `authorized_keys`. | | **ACME auto-renewal** | Built-in HTTP-01 responder on port 80. Let's Encrypt certificate for the apex, renewal 30 days before expiry. Cache in `data_dir/acme/`, mode `0700`. | | **Session resume** | Client crashed? On reconnect it re-attaches to the same `public_url` within a 30-second grace period. Works **across transports** — you can drop a QUIC session and restore it over the TCP fallback. | | **Rate limiting** | Per-identity token-bucket via `governor` plus a period quota. Fully partitioned per-core, the aggregate cap is respected. When the quota is exhausted the server sends the client `retry_after_ms`. | | **Passive HTTP inspector** | `--inspect` enables a local admin UI on `localhost:4040` — method, path, status, and duration of every request. | | **Login-page auth** | `krot http --auth user:pass` serves a styled sign-in page with the krot brand mark; a successful login installs a session cookie (`HttpOnly; SameSite=Lax`, 8h rolling TTL). For machines — `--api-key SECRET` (`X-API-Key` / `Authorization: Bearer`). File/env variants for non-dev use. Constant-time compare, no secrets in logs. | | **Admin API** | `/admin/v1/{tunnels,keys,metrics}` HTTP endpoint on `127.0.0.1:9700`. Bearer-token auth, Prometheus metrics, key revocation in under 1 second. | | **Federated relays** | Multi-relay setup: `federation=peer1,peer2` in `authorized_keys`. The client publishes one tunnel on several relays, DNS/CDN handles failover. | | **Hot-reload of authorization** | Key removed from `authorized_keys`? Active sessions get a revoke notification within <1s via the `notify` watcher. Same mechanism for the peer list. | | **Graceful shutdown** | `Ctrl+C` sends a clean `ServerBye` to every open session, waits for ACKs, then closes the endpoint. Deadline 5 seconds. | --- ## Installation Four ways to get `krot-server` and `krot-client` binaries. ### Prebuilt binaries (recommended) Download from the [latest release](https://github.com/krottunnel/krot/releases/latest): | Platform | Archive | |---|---| | Linux · x86_64 | `krot-vX.Y.Z-x86_64-unknown-linux-musl.tar.gz` | | Linux · ARM64 | `krot-vX.Y.Z-aarch64-unknown-linux-musl.tar.gz` | | macOS · Apple Silicon | `krot-vX.Y.Z-aarch64-apple-darwin.tar.gz` | | Windows · 64-bit | `krot-vX.Y.Z-x86_64-pc-windows-msvc.zip` | | Windows · 32-bit | `krot-vX.Y.Z-i686-pc-windows-msvc.zip` | Each archive contains `krot-server`, `krot` (the client CLI), `LICENSE-*`, `README.md`. Verify the accompanying `.sha256`, extract, and move the binaries into your `PATH`. Intel Mac users: run the `aarch64-apple-darwin` build under Rosetta 2, or use `cargo install --git` below. ### With cargo Requires a stable Rust toolchain (get one from [rustup.rs](https://rustup.rs)): ```bash cargo install --git https://github.com/krottunnel/krot krot-server krot-client ``` Binaries land in `~/.cargo/bin/` on unix or `%USERPROFILE%\.cargo\bin\` on Windows. ### With Docker (server only) ```bash docker pull krottunnel/krot-server:latest ``` Multi-arch image (`linux/amd64`, `linux/arm64`). ### From source ```bash git clone https://github.com/krottunnel/krot cd krot cargo build --release --workspace # → target/release/krot-server, target/release/krot-client ``` --- ## Quick start Prerequisites: a VPS with a public IP, your own domain, wildcard DNS `*.krot.example → `, ports 80/443/7853 open. ### 1. Server ```bash # prebuilt image from Docker Hub — recommended: docker pull krottunnel/krot-server:latest # or build locally: # docker build -t krottunnel/krot-server:dev . docker run -d --name krot \ -p 7853:7853/udp \ -p 7853:7853/tcp \ -p 80:80/tcp \ -p 443:443/tcp \ -v krot-data:/var/lib/krot \ -v krot-config:/etc/krot \ krottunnel/krot-server:latest \ --domain krot.example \ --acme-contact mailto:admin@krot.example \ --acme-production \ --tcp-fallback-bind 0.0.0.0:7853 # the server prints a one-shot admin token: docker logs krot | grep KROT_ADMIN_TOKEN # KROT_ADMIN_TOKEN=R54VHZ9FD0JJ44GPDZFEJZ7DV8WFB77JHYHVPFF64BF677X7WX70 ``` > **Root/privileges.** Defaults `--http-bind 0.0.0.0:80` and > `--https-bind 0.0.0.0:443` are privileged ports. The Docker container > above runs via `-p 80:80/tcp`, where Docker handles the mapping. > Running **without Docker** requires either `sudo` or `setcap > 'cap_net_bind_service=+ep' target/release/krot-server`. For local > development, remap to unprivileged ports: `--http-bind 127.0.0.1:8080 > --https-bind 127.0.0.1:8443`. ### 2. Client ```bash krot init --server krot.example --admin-token R54VHZ9FD0JJ44... # → enrolled at krot.example:7853 ``` ### 3. Publish a local service ```bash krot http 3000 --name alice --inspect # → https://alice.krot.example # → inspector: http://127.0.0.1:4040 ``` Done. External requests to `https://alice.krot.example` flow through the server, TLS-encrypted end-to-end to your client. --- ## CLI reference ### `krot-server` | Flag | Default | What it does | |---|---|---| | `--domain ` | — | Enables DomainMode. Without it — IpMode (TCP tunnels only, self-signed cert with pinned fingerprint). | | `--acme-contact mailto:...` | — | Obtain the apex certificate via ACME (Let's Encrypt **staging** by default). | | `--acme-production` | off | Switch to LE production. | | `--tls-cert / --tls-key` | — | Alternative to ACME — bring your own PEM certificate. | | `--bind` | `0.0.0.0:7853` | UDP address of the QUIC endpoint. | | `--tcp-fallback-bind ` | disabled | TCP+TLS listener for clients with UDP blocked. | | `--http-bind` / `--https-bind` | `0.0.0.0:80` / `:443` | Addresses for the 80/443 routers. | | `--tcp-port-pool ` | `10000-19999` | Port pool for TCP tunnels. | | `--cores N` | `available_parallelism()` | Number of worker threads. The `bw=` cap is partitioned per-core. | | `--data-dir` | `/var/lib/krot` | Persistent state (identity cert, ACME cache, admin_token hash). | | `--authorized-keys` | `/etc/krot/authorized_keys` | SSH-style file of authorized keys. Hot-reload. | | `--peer-list` | `/etc/krot/peers.txt` | Static list of federated relays (one apex per line). Hot-reload. | | `--admin-bind` | `127.0.0.1:9700` | Structured admin API. Empty value disables it. | | `--issue-admin-token` | off | Issue a new admin token even if `authorized_keys` is non-empty. | ### `krot` (client) | Subcommand | What it does | |---|---| | `krot init --server HOST --admin-token TOKEN [--fingerprint sha256:HEX]` | Generate identity, enroll the public key. IpMode uses the pinned fingerprint; DomainMode uses a real CA. | | `krot tcp ` | Publish a TCP service (`ssh`, DB, minecraft, anything) as `tcp://:`. | | `krot http [flags]` | Publish an HTTP service as `https://