mirror of
https://github.com/ekzhang/bore.git
synced 2026-04-18 22:50:21 +00:00
2.8 KiB
2.8 KiB
AGENTS.md
Project Overview
Bore is a modern, simple TCP tunnel in Rust that exposes local ports to a remote server, bypassing NAT. It's an alternative to localtunnel/ngrok. The crate is published as bore-cli with binary name bore.
Build & Development Commands
cargo build --all-features # Build
cargo test # Run all tests
cargo test basic_proxy # Run a single test by name
cargo fmt -- --check # Check formatting
cargo clippy -- -D warnings # Lint (CI treats warnings as errors)
RUST_LOG=debug cargo test # Run tests with debug logging
Architecture
The codebase is ~400 lines of async Rust using Tokio. No unsafe code (#![forbid(unsafe_code)]).
Modules
main.rs— CLI entry point using clap. Two subcommands:local(client) andserver.shared.rs— Protocol definitions.ClientMessage/ServerMessageenums serialized as JSON over TCP with null-byte delimiters.Delimited<U>wraps any async stream for framed JSON I/O. Key constants:CONTROL_PORT = 7835,MAX_FRAME_LENGTH = 256,NETWORK_TIMEOUT = 3s.auth.rs— Optional HMAC-SHA256 challenge-response authentication. Secret is SHA256-hashed before use. Constant-time comparison.client.rs—Clientconnects to server's control port, sendsHello(port), receives assigned port. For each incomingConnection(uuid), opens a new TCP connection, sendsAccept(uuid), then bidirectionally proxies between local service and tunnel.server.rs—Serverlistens on control port. Allocates tunnel ports (random selection, 150 attempts). Stores pending connections inDashMap<Uuid, TcpStream>with 10-second expiry. Sends heartbeats every 500ms.
Protocol Flow
- Client connects to server on control port (7835)
- Optional auth: server sends
Challenge(uuid), client responds withAuthenticate(hmac) - Client sends
Hello(desired_port), server responds withHello(actual_port)and starts tunnel listener - When external traffic hits the tunnel port, server stores the connection by UUID, sends
Connection(uuid)to client - Client opens a new connection to server, sends
Accept(uuid), server pairs streams, bidirectional copy begins
Key Patterns
Delimited<U>for framed JSON messaging with null-byte delimiters (viatokio_util::codec)Arc<DashMap>for lock-free concurrent pending connection storageArc<Client>/Arc<Server>shared across spawned Tokio taskstokio::io::copy_bidirectionalfor efficient TCP proxyinganyhow::Resultwith.context()for error propagation
Testing
Tests are in tests/e2e_test.rs (integration) and tests/auth_test.rs (auth unit tests). Integration tests use a lazy_static mutex (SERIAL_GUARD) to run serially and avoid port conflicts. CI retries tests up to 3 times due to potential port contention.