# Codive Relay - Secure Tunneling Server
A production-ready relay server that enables secure remote access to local Codive servers through encrypted WebSocket tunnels. Similar to ngrok, but self-hostable with end-to-end encryption.
## Features
### Security
- **End-to-End Encryption**: XChaCha20-Poly1305 encryption with keys shared via URL fragment (never sent to server)
- **JWT Authentication**: Token-based auth with expiration, claims, and revocation support
- **Simple Token Auth**: Lightweight alternative for self-hosted deployments
- **Auth Rate Limiting**: Automatic IP bans after failed authentication attempts
- **Security Headers**: HSTS, CSP, X-Frame-Options, X-Content-Type-Options on all responses
- **Memory Protection**: Cryptographic keys are zeroized when dropped
### Abuse Prevention
- **IP Rate Limiting**: Configurable max tunnels per IP address
- **Tunnel TTL**: Auto-expire tunnels after configurable duration
- **Idle Timeout**: Close inactive tunnels automatically
- **Random IDs Only**: Prevent subdomain squatting on public relays
### Protocol
- **WebSocket-based**: Reliable, bidirectional communication
- **HTTP Proxying**: Full HTTP request/response forwarding
- **SSE Streaming**: Server-Sent Events pass through correctly
- **Keep-Alive**: Ping/pong for connection health monitoring
- **Automatic Reconnection**: Exponential backoff on disconnect
## Quick Start
### Self-Hosted (Development)
```bash
# Terminal 1: Start relay server
cargo run -p codive-relay -- -v
# Terminal 2: Start codive with tunnel
cargo run -p codive-cli -- --serve --tunnel -v
# Terminal 3: Connect as client (use URL from Terminal 2)
cargo run -p codive-cli -- --connect "http://abc123.localhost:3001#<key>"
```
### Production Deployment
```bash
# Build release binary
cargo build -p codive-relay --release
# Run with production settings
./target/release/codive-relay \
--host 0.0.0.0 \
--port 443 \
--domain relay.yourdomain.com \
--https \
--require-auth \
--jwt-secret "your-secret-key" \
-v
```
### Public Relay (Zero-Friction)
For a public relay where users don't need to authenticate:
```bash
./target/release/codive-relay \
--host 0.0.0.0 \
--domain relay.yourdomain.com \
--https \
--random-ids-only \
--max-tunnel-age 28800 \
--max-idle-time 1800 \
--max-tunnels-per-ip 3 \
-v
```
Users can then simply run:
```bash
codive --serve --tunnel
# Tunnel URL displayed, no auth needed!
```
## CLI Reference
```
codive-relay [OPTIONS]
Options:
--host <HOST> Host to bind to [default: 127.0.0.1]
--port <PORT> Port to bind to [default: 3001]
--domain <DOMAIN> Base domain for tunnel URLs [default: localhost:3001]
--https Use HTTPS for tunnel URLs
--timeout <SECONDS> Request timeout [default: 30]
Rate Limiting:
--max-tunnels-per-ip <N> Max tunnels per IP [default: 10]
--max-tunnel-age <SECONDS> Tunnel TTL (0 = no limit) [default: 0]
--max-idle-time <SECONDS> Idle timeout (0 = no limit) [default: 0]
--random-ids-only Force random tunnel IDs only
Authentication:
--require-auth Require authentication for connections
--auth-token <TOKEN> Valid auth token (can specify multiple)
--jwt-secret <SECRET> JWT secret (enables JWT mode)
--jwt-validity <SECONDS> JWT token validity [default: 3600]
--max-auth-failures <N> Failed attempts before ban [default: 5]
--auth-ban-duration <SECONDS> Ban duration [default: 300]
Other:
-v, --verbose Increase verbosity (can repeat)
-h, --help Print help
-V, --version Print version
```
## Architecture
```
┌─────────────────┐ ┌─────────────────────────┐ ┌──────────────────┐
│ Remote Client │────▶│ Relay Server │────▶│ Agent Server │
│ │ │ relay.yourdomain.com │ │ (local machine) │
└─────────────────┘ └─────────────────────────┘ └──────────────────┘
│ │ │
HTTPS request Routes by subdomain WebSocket tunnel
to tunnel URL (abc123.relay...) to local agent
│ │ │
└─────────────────────────┴──────────────────────────────┘
End-to-end encrypted (key in URL fragment)
```
### Crate Structure
- **codive-relay**: The relay server binary and HTTP/WebSocket handling
- **codive-tunnel**: Shared library with protocol types, encryption, and wire format
### Protocol Flow
1. Agent connects to relay via WebSocket (`GET /agent`)
2. Agent sends `Hello` message with optional auth token
3. Relay validates auth, assigns tunnel ID, sends `Welcome` with tunnel URL
4. Relay forwards HTTP requests to agent as encrypted `HttpRequest` messages
5. Agent decrypts, forwards to local server, encrypts response
6. Relay returns response to original HTTP client
## Configuration Examples
### Minimal (Development)
```bash
codive-relay
```
### With Authentication
```bash
codive-relay \
--require-auth \
--auth-token "secret-token-1" \
--auth-token "secret-token-2"
```
### With JWT
```bash
codive-relay \
--require-auth \
--jwt-secret "your-256-bit-secret" \
--jwt-validity 7200
```
### Public Relay (Recommended Settings)
```bash
codive-relay \
--host 0.0.0.0 \
--domain relay.example.com \
--https \
--random-ids-only \
--max-tunnel-age 28800 \
--max-idle-time 1800 \
--max-tunnels-per-ip 3 \
--max-auth-failures 5 \
--auth-ban-duration 300
```
## Deployment with Reverse Proxy
### Nginx
```nginx
server {
listen 443 ssl http2;
server_name relay.yourdomain.com *.relay.yourdomain.com;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
location / {
proxy_pass http://127.0.0.1:3001;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_read_timeout 86400;
}
}
```
### Caddy
```
*.relay.yourdomain.com, relay.yourdomain.com {
reverse_proxy localhost:3001
}
```
### Docker
```dockerfile
FROM rust:1.75 as builder
WORKDIR /app
COPY . .
RUN cargo build -p codive-relay --release
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/*
COPY --from=builder /app/target/release/codive-relay /usr/local/bin/
EXPOSE 3001
CMD ["codive-relay", "--host", "0.0.0.0"]
```
## Testing
```bash
# Run all tunnel tests
cargo test -p codive-tunnel -p codive-relay
# Run specific test
cargo test -p codive-relay test_jwt_token
# With output
cargo test -p codive-relay -- --nocapture
```
Current test coverage: **109 tests** (47 relay + 62 tunnel)
## Future Roadmap
### Tier 2: Reliability
- [ ] Configurable request timeouts via CLI
- [ ] Graceful shutdown with request draining
- [ ] Error classification (retryable vs permanent)
- [ ] Circuit breaker pattern
### Tier 3: Operations
- [ ] Prometheus metrics endpoint (`/metrics`)
- [ ] Enhanced health checks with tunnel stats
- [ ] Admin API (list tunnels, force disconnect)
- [ ] Request/response logging (opt-in)
### Tier 4: Features
- [ ] WebSocket proxying (bidirectional)
- [ ] Custom domain support
- [ ] Request inspection UI
- [ ] Bandwidth limiting per tunnel
## Contributing
### Getting Started
1. Fork the repository
2. Create a feature branch: `git checkout -b feature/my-feature`
3. Make changes and add tests
4. Run tests: `cargo test -p codive-tunnel -p codive-relay`
5. Run linter: `cargo clippy -p codive-tunnel -p codive-relay`
6. Format code: `cargo fmt`
7. Submit a pull request
### Code Structure
```
crates/
├── codive-tunnel/ # Shared library
│ ├── src/
│ │ ├── lib.rs # Public exports
│ │ ├── crypto.rs # XChaCha20-Poly1305 encryption
│ │ └── protocol.rs # Wire protocol, message types
│ └── Cargo.toml
│
└── codive-relay/ # Relay server
├── src/
│ ├── main.rs # CLI and server startup
│ ├── lib.rs # Router and middleware
│ ├── state.rs # Shared state, auth, rate limiting
│ ├── tunnel.rs # Tunnel connection management
│ └── routes/
│ ├── mod.rs # Route definitions
│ ├── agent.rs # WebSocket handler
│ └── proxy.rs # HTTP proxy handler
└── Cargo.toml
```
### Adding a New Feature
1. **Protocol changes**: Update `codive-tunnel/src/protocol.rs`
2. **Server logic**: Update `codive-relay/src/routes/` or `state.rs`
3. **CLI flags**: Update `codive-relay/src/main.rs`
4. **Tests**: Add to the `#[cfg(test)]` module in relevant file
### Commit Message Format
```
<type>: <description>
<body>
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: <name> <email>
```
Types: `feat`, `fix`, `docs`, `test`, `refactor`, `perf`
## License
This project is licensed under the MIT License - see the LICENSE file for details.
## Acknowledgments
- Inspired by [ngrok](https://ngrok.com), [localtunnel](https://localtunnel.me), and [Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/)
- Built with [axum](https://github.com/tokio-rs/axum), [tokio](https://tokio.rs), and [chacha20poly1305](https://docs.rs/chacha20poly1305)