Compare commits
1 Commits
v0.1.0-bet
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
278cbf4fb4 |
@@ -24,7 +24,7 @@ Most VPN apps ask you to trust the app vendor's servers. koridor doesn't have an
|
|||||||
## Features
|
## Features
|
||||||
|
|
||||||
- **Full-device tunnel** — a TUN-based VPN, not just an app-aware SOCKS proxy. Every app on the device is covered, with no per-app setup.
|
- **Full-device tunnel** — a TUN-based VPN, not just an app-aware SOCKS proxy. Every app on the device is covered, with no per-app setup.
|
||||||
- **Bring your own server** — connects to any SSH server with `AllowTcpForwarding yes`. No special server-side software required.
|
- **Bring your own server** — connects to any SSH server with `AllowTcpForwarding yes`. No special server-side software required. (One opt-in exception: UDP port forwarding provisions a relay script and an `authorized_keys` line on your server — see the [Server Quickstart](docs/server-quickstart.md#6-optional-udp-port-forwarding).)
|
||||||
- **Simple onboarding** — set up a connection profile, toggle on, done.
|
- **Simple onboarding** — set up a connection profile, toggle on, done.
|
||||||
- **Fail-closed reconnects** — transient drops are retried with exponential backoff; if the tunnel can't recover, the route is torn down rather than silently leaking traffic in the open.
|
- **Fail-closed reconnects** — transient drops are retried with exponential backoff; if the tunnel can't recover, the route is torn down rather than silently leaking traffic in the open.
|
||||||
- **Tunnel-only DNS** — lookups are resolved through the server's own resolver over the tunnel, never leaked to a third-party DNS provider.
|
- **Tunnel-only DNS** — lookups are resolved through the server's own resolver over the tunnel, never leaked to a third-party DNS provider.
|
||||||
@@ -47,6 +47,11 @@ Releases are published on the [Releases](../../releases) page.
|
|||||||
|
|
||||||
Coming soon.
|
Coming soon.
|
||||||
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
- [Server Quickstart](docs/server-quickstart.md) — what your SSH server needs, the
|
||||||
|
keypair, host-key trust, and what UDP forwarding provisions on your box
|
||||||
|
|
||||||
## Architecture
|
## Architecture
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|||||||
168
docs/server-quickstart.md
Normal file
168
docs/server-quickstart.md
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
# Running Your Own koridor Server
|
||||||
|
|
||||||
|
koridor has no server component. It is a client that speaks standard SSH to a
|
||||||
|
server you already operate — a VPS, a NAS, a home box, anything running `sshd`.
|
||||||
|
There is nothing to install on the far end and no koridor-operated backend.
|
||||||
|
|
||||||
|
This is the whole server story for normal TCP traffic. One optional feature —
|
||||||
|
UDP port forwarding — does provision something on your server, and it is
|
||||||
|
covered separately in step 6 because it changes your `authorized_keys`.
|
||||||
|
|
||||||
|
## 1. What you need
|
||||||
|
|
||||||
|
- An SSH server you control, reachable from wherever the device will be.
|
||||||
|
- An SSH keypair. **You supply the key** — koridor does not generate one for the
|
||||||
|
tunnel, so create it first.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh-keygen -t ed25519 -f ~/.ssh/koridor_key
|
||||||
|
```
|
||||||
|
|
||||||
|
The private key is what you paste into the app. It can have a passphrase; koridor
|
||||||
|
prompts for it and keeps it in the OS credential store.
|
||||||
|
|
||||||
|
## 2. Server requirements (TCP)
|
||||||
|
|
||||||
|
`AllowTcpForwarding yes` — and that is the entire requirement.
|
||||||
|
|
||||||
|
It is **on by default** in OpenSSH, so most servers need no configuration at
|
||||||
|
all. Check what yours is actually set to:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo sshd -T | grep -i allowtcpforwarding
|
||||||
|
```
|
||||||
|
|
||||||
|
If it says `no`, enable it in `/etc/ssh/sshd_config`:
|
||||||
|
|
||||||
|
```
|
||||||
|
AllowTcpForwarding yes
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo sshd -t && sudo systemctl reload sshd
|
||||||
|
```
|
||||||
|
|
||||||
|
`sshd -t` validates the config before the reload — run it, or a typo takes SSH
|
||||||
|
out remotely.
|
||||||
|
|
||||||
|
### What you do *not* need
|
||||||
|
|
||||||
|
This trips up people who have set up a VPN server before. None of the following
|
||||||
|
applies to koridor:
|
||||||
|
|
||||||
|
- **No `net.ipv4.ip_forward`.** koridor does not forward packets through the
|
||||||
|
server; `sshd` opens each outgoing connection itself.
|
||||||
|
- **No iptables or nftables masquerade rules.** Each TCP flow is an ordinary
|
||||||
|
SSH `direct-tcpip` channel, so the server makes its own outbound connections
|
||||||
|
and the kernel never routes between interfaces.
|
||||||
|
- **No `/dev/net/tun` and no TUN interface on the server.** The TUN device lives
|
||||||
|
on the client only.
|
||||||
|
- **No root.** A normal unprivileged SSH user is enough.
|
||||||
|
- **No konduit-style provisioning, bootstrap, or peer list.** There is no
|
||||||
|
control API and nothing to reload.
|
||||||
|
|
||||||
|
The cost on the server is one SSH session per active TCP flow. A busy browser
|
||||||
|
tab set will show more `sshd` sessions than you might expect — that is expected,
|
||||||
|
not a leak.
|
||||||
|
|
||||||
|
## 3. Add the profile
|
||||||
|
|
||||||
|
In the app, create a connection profile:
|
||||||
|
|
||||||
|
| Field | Value |
|
||||||
|
|---|---|
|
||||||
|
| Host | Your server's hostname or IP |
|
||||||
|
| Port | SSH port, `22` unless you changed it |
|
||||||
|
| Username | The SSH user whose key you installed |
|
||||||
|
| Private key | Contents of the `.pub`-less private key file (PEM) |
|
||||||
|
| Passphrase | Only if the key has one |
|
||||||
|
|
||||||
|
The host may be a `~/.ssh/config` alias — koridor resolves it and pins the host
|
||||||
|
key against whatever the alias resolves to, not the alias name.
|
||||||
|
|
||||||
|
## 4. Trust the host key
|
||||||
|
|
||||||
|
The first connection to a new server does **not** connect. koridor shows you the
|
||||||
|
host key fingerprint and waits for you to accept it. This is deliberate: the key
|
||||||
|
is established once, on your say-so, and never silently assumed.
|
||||||
|
|
||||||
|
Compare the fingerprint against the one SSH already knows:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
ssh-keygen -lf /etc/ssh/ssh_ed25519_key.pub
|
||||||
|
```
|
||||||
|
|
||||||
|
If the server is remote, compare against the fingerprint `ssh` shows you on
|
||||||
|
first connect from a machine you trust.
|
||||||
|
|
||||||
|
Once pinned, koridor checks the key on every connection. If it later changes,
|
||||||
|
koridor stops and tells you — it does not retry or fall back, because a changed
|
||||||
|
host key means you are no longer talking to the same machine.
|
||||||
|
|
||||||
|
## 5. Connect
|
||||||
|
|
||||||
|
Toggle the profile on. Traffic routes through the tunnel, and DNS lookups go
|
||||||
|
through the server's own resolver over the tunnel rather than to a third-party
|
||||||
|
resolver.
|
||||||
|
|
||||||
|
If the tunnel cannot recover after a drop, koridor tears the route down instead
|
||||||
|
of leaving traffic to leak in the open. That is the intended behaviour, not a
|
||||||
|
bug.
|
||||||
|
|
||||||
|
Transient failures retry with exponential backoff up to roughly two minutes.
|
||||||
|
Failures that retrying cannot fix — a private key that will not decode, a wrong
|
||||||
|
passphrase, a rejected public key — fail immediately instead of sitting out that
|
||||||
|
schedule.
|
||||||
|
|
||||||
|
## 6. Optional: UDP port forwarding
|
||||||
|
|
||||||
|
**Off by default.** SSH has no UDP channel type, so koridor relays specific
|
||||||
|
allow-listed UDP ports through a second, restricted SSH connection.
|
||||||
|
|
||||||
|
Enabling it **provisions itself on your server**, automatically, the first time
|
||||||
|
you turn it on:
|
||||||
|
|
||||||
|
- Installs a managed script at `~/.koridor/udp-relay.sh` for the SSH user.
|
||||||
|
- Adds one line to that user's `~/.ssh/authorized_keys`, marked
|
||||||
|
`# koridor-udp-relay`, restricted with a forced command so the key can only
|
||||||
|
run that relay.
|
||||||
|
- Requires **`socat`** on the server.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo apt install socat # or: dnf install socat
|
||||||
|
```
|
||||||
|
|
||||||
|
Both changes are idempotent and reversible — clearing the allow-list removes the
|
||||||
|
`authorized_keys` line, leaving every other key in the file untouched. Every
|
||||||
|
other line in `authorized_keys` is preserved across re-syncs.
|
||||||
|
|
||||||
|
Ports are gated by destination port only, not destination IP: any host on an
|
||||||
|
allow-listed port can be relayed to. Datagrams are piped through `socat` rather
|
||||||
|
than framed, so two datagrams written back to back are not guaranteed to arrive
|
||||||
|
as two separate reads — fine for WireGuard and similar retrying protocols, not
|
||||||
|
fine as a general UDP transport.
|
||||||
|
|
||||||
|
The main use case is running another UDP-based tool, most often a second VPN
|
||||||
|
like WireGuard, through koridor.
|
||||||
|
|
||||||
|
## 7. Optional: TCP local forwards
|
||||||
|
|
||||||
|
For per-app routing without the TUN, a profile can carry classic SSH local
|
||||||
|
forward rules in `LOCAL_PORT:IP:PORT` form. These are ordinary `-L` forwards and
|
||||||
|
need nothing extra on the server.
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
| Symptom | Cause |
|
||||||
|
|---|---|
|
||||||
|
| Refuses to connect, no fingerprint shown | A profile with no pinned host key. Accept the fingerprint on first connect. |
|
||||||
|
| "host key changed" error | The server's key really changed — a rebuild, or you are not talking to the same host. Investigate before accepting the new one; koridor will not retry. |
|
||||||
|
| Connects, but no traffic | Check `AllowTcpForwarding` with `sshd -T`. |
|
||||||
|
| Works with `ssh`, fails in the app | Usually the key. koridor wants the private key contents, not a path, and the key must be PEM. |
|
||||||
|
| Sits retrying for two minutes then fails | A fatal error being treated as transient: bad key, wrong passphrase, or rejected public key. These normally fail at once — if yours does not, the error text is the useful part. |
|
||||||
|
| Second VPN (WireGuard) comes up but passes no traffic | WireGuard is UDP and UDP forwarding is off. See step 6. |
|
||||||
|
| UDP forwarding fails at setup | `socat` missing on the server, or the SSH user cannot write to its own `~/.ssh/`. |
|
||||||
|
|
||||||
|
Logs follow the usual pattern: connection failures retry on a backoff schedule,
|
||||||
|
and anything that retrying cannot fix is reported immediately rather than
|
||||||
|
silently repeated.
|
||||||
Reference in New Issue
Block a user