# Layover
SSH through firewalls. Layover is a TCP relay that tunnels your SSH connections through restrictive networks like airport wifi.
```
You (airport wifi) ──TLS:443──▶ Layover Server ──TCP:22──▶ Your Server
```
Restrictive networks block SSH (port 22) but allow HTTPS (port 443). Layover runs a relay on port 443, so your SSH traffic looks like normal web traffic to the network.
## Quick Start
```bash
# Install
cargo install layover
# SSH through Layover (one-liner)
ssh -o ProxyCommand="layover connect %h:%p" user@myserver.com
```
That's it. Your SSH connection is relayed through `layover.sh` over TLS on port 443.
## SSH Config
Instead of passing `-o ProxyCommand=...` every time, add it to your SSH config:
```bash
# Route specific hosts through Layover
layover setup --host myserver.com --host "*.work.com" --install
# Or route everything through Layover
layover setup --install
```
This appends the config to `~/.ssh/config`. You can also preview what it'll write by omitting `--install`:
```bash
$ layover setup --host myserver.com
Host myserver.com
ProxyCommand layover connect %h:%p --server layover.sh
```
Re-running `--install` replaces the previous Layover block, so it's safe to run multiple times.
## Self-Hosting
You can run your own Layover relay server instead of using `layover.sh`.
### Setup
You need a server with:
- A public IP reachable on port 443
- A domain name pointing to it
- A TLS certificate (e.g., from Let's Encrypt)
```bash
# Get a TLS cert with certbot
sudo certbot certonly --standalone -d relay.example.com
# Run the relay server
layover serve \
--cert /etc/letsencrypt/live/relay.example.com/fullchain.pem \
--key /etc/letsencrypt/live/relay.example.com/privkey.pem
```
The server listens on `0.0.0.0:443` by default. Change it with `--listen`:
```bash
layover serve --listen 0.0.0.0:8443 --cert cert.pem --key key.pem
```
### Using Your Server
Point the client at your server instead of the default:
```bash
ssh -o ProxyCommand="layover connect %h:%p --server relay.example.com" user@myserver.com
```
Or set it globally:
```bash
export LAYOVER_SERVER=relay.example.com
ssh -o ProxyCommand="layover connect %h:%p" user@myserver.com
```
Or configure it in SSH config:
```bash
layover setup --server relay.example.com --install
```
### Development Mode
For local testing, you can skip TLS:
```bash
# Server
layover serve --no-tls --listen 127.0.0.1:4443
# Client
ssh -o ProxyCommand="layover connect %h:%p --server 127.0.0.1:4443 --no-tls" user@myserver.com
```
## How It Works
1. SSH invokes `layover connect` as a ProxyCommand
2. The client opens a TLS connection to the Layover relay server on port 443
3. The client sends the destination (`host:port`)
4. The relay server connects to the destination
5. Bytes flow bidirectionally: SSH ↔ Layover client ↔ Layover server ↔ destination
6. To the restrictive network, it all looks like HTTPS traffic
## CLI Reference
### `layover connect <destination>`
ProxyCommand mode. Connects to the relay server, requests the destination, and bridges stdin/stdout.
| `--server` | Relay server address | `layover.sh` |
| `--no-tls` | Disable TLS (dev only) | off |
The server can also be set via `LAYOVER_SERVER` environment variable.
### `layover serve`
Run the relay server.
| `--listen` | Address to bind | `0.0.0.0:443` |
| `--cert` | TLS certificate (PEM) | required |
| `--key` | TLS private key (PEM) | required |
| `--no-tls` | Disable TLS (dev only) | off |
### `layover setup`
Generate or install SSH config for Layover.
| `--server` | Relay server address | `layover.sh` |
| `--host` | Host pattern(s) to route (repeatable) | `*` |
| `--install` | Write to `~/.ssh/config` | off (print only) |
| `--no-tls` | Include `--no-tls` in ProxyCommand | off |
When using `Host *` (the default), an exclusion entry for the relay server is automatically added to prevent routing loops.
## Building from Source
```bash
git clone https://github.com/Lukas-Dresel/ssh-layover.git
cd layover
cargo build --release
# Binary is at target/release/layover
```
## License
MIT