codive-relay 0.1.0

Relay server for secure tunneling
Documentation
# 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