pb-mapper is a Rust-based service mapping system that exposes multiple local TCP/UDP services through a single public server port. Unlike frp-style per-service port mapping, pb-mapper uses a service key registry so many local services can be published behind one public port and accessed by others through the same server.
- Easy to use by design: a single public server port plus a service-key registry removes per-service port planning; the same flow is shared by CLI and GUI.
- Extensible architecture: clear server/client split (
pb-mapper-server,pb-mapper-server-cli,pb-mapper-client-cli) with shared protocol and utilities insrc/commonandsrc/utils, making new features and transports easier to add. - Encryption support: optional message encryption for forwarded traffic using AES-256-GCM (via
ring), enabled with the--codecflag when registering services. - Performance: in real use (e.g., running a Palworld UDP server), latency is comparable to using frp with a directly exposed remote port.
If you use an AI coding agent (e.g., Claude Code, Cursor, Kiro), invoke the built-in deployment skill for a fully interactive, one-click deploy — no need for GitHub access on the remote host:
- Server deploy:
/pb-mapper-server-deploy— downloads the binary locally, uploads via SCP, and sets up a systemd service on the remote host. - Client tunnel deploy:
/pb-mapper-client-cli-deploy— same local-download-then-upload flow forpb-mapper-client-cli, with systemd service and end-to-end validation.
The skills interactively collect all parameters (SSH credentials, ports, encryption keys) and handle proxy fallback if GitHub downloads fail on your local network.
If the remote host has direct GitHub access, one command installs pb-mapper-server as a systemd service on Linux (x86_64, musl build). Defaults: port 7666, enables --use-machine-msg-header-key, and persists key to /var/lib/pb-mapper-server/msg_header_key.
curl -fsSL https://raw.githubusercontent.com/acking-you/pb-mapper/master/scripts/install-server-github.sh | bashAfter install, load the same key for pb-mapper-server-cli / pb-mapper-client-cli:
export MSG_HEADER_KEY="$(cat /var/lib/pb-mapper-server/msg_header_key)"- User Guide (build/run/use):
docs/user-guide.md - Docker Server Guide:
DOCKER_README.md - Chinese docs:
README.zh-CN.md,docs/user-guide.zh-CN.md
- pb-mapper-server: central router (default port
7666) - pb-mapper-server-cli: register local TCP/UDP services to the server
- pb-mapper-client-cli: connect to a registered service and expose a local port
- Flutter UI (
ui/): GUI for server and client management
The diagram above shows the three-zone architecture:
- Local Service Side (green):
pb-mapper-server-cli(or Flutter UI) registers a local TCP/UDP service with the public server. - Public Network (blue):
pb-mapper-servermaintains a service registry, manages connections, and forwards data bidirectionally. - Remote Client Side (orange):
pb-mapper-client-cli(or Flutter UI) subscribes to a service key and exposes it as a local port.
Suppose you run a web server on localhost:8080 at home, and want to access it from a coffee shop.
Home LAN Public Server Coffee Shop
┌─────────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ Web Server :8080 │ │ pb-mapper-server│ │ Browser :3000 │
│ ↑ │ │ :7666 │ │ ↑ │
│ server-cli ────────┼──────►│ key='web' ──────┼◄──────┼── client-cli │
└─────────────────────┘ └──────────────────┘ └──────────────────┘
Step 1 – On the public server, start the central router:
pb-mapper-server --port 7666Step 2 – At home, register your web server:
pb-mapper-server-cli --server <public-ip>:7666 --key web --local 127.0.0.1:8080Step 3 – At the coffee shop, subscribe and expose locally:
pb-mapper-client-cli --server <public-ip>:7666 --key web --local 127.0.0.1:3000Now open http://localhost:3000 in the coffee-shop browser — traffic flows through the public server back to your home web server.
- Binaries live in
src/bin/and share protocol + networking helpers insrc/commonandsrc/utils. - Server/Client internals are split across
src/pb_server,src/local/server, andsrc/local/client.
- Layering:
- UI screens/widgets:
ui/lib/src/views,ui/lib/src/widgets. - Typed UI API:
ui/lib/src/ffi/pb_mapper_api.dart. - FFI transport + isolate dispatch:
ui/lib/src/ffi/pb_mapper_service.dart. - Raw FFI bindings:
ui/lib/src/ffi/pb_mapper_ffi.dart. - Rust FFI crate:
ui/native/pb_mapper_ffi(C ABI + JSON response envelope).
- UI screens/widgets:
- Threading: All FFI calls are executed on a background isolate to avoid blocking Flutter's UI thread.
- Native responses: Rust returns JSON strings (
{success, message, data}) to avoid generated bindings and keep the ABI stable during iteration.
src/: Rust backendui/: Flutter UI + native bridgedocs/: documentationdocker/,services/,scripts/,tests/: deployment and toolingskills/: AI coding agent deployment skills (server deploy, client-cli deploy)
For build/run/usage instructions, see the User Guide.