GoPublic is a self-hosted reverse proxy service similar to ngrok. It allows exposing local services to the public internet via a secure tunnel. The system consists of three main components:
- Server: Hosted on a public VPS. Handles public HTTP/HTTPS traffic, user authentication, and tunnel management.
- Client (Agent): Runs on the user's local machine. Establishes a persistent connection to the Server and proxies traffic.
- Web Dashboard: A web interface for users to register, view tokens, and manage domains.
- SSO Only: Users register/login via Telegram OAuth (Login Widget).
- Account Creation: Upon first login:
- A unique User ID is generated.
- A cryptographically secure Auth Token is generated using 256 bits of entropy (e.g.,
sk_live_aBcD1234...). This token effectively is the user identity for the CLI. - Domain Assignment: The system automatically generates 3 random, memorable subdomains (e.g.,
misty-river-123,silent-star-456,bold-eagle-789) and assigns them to the user.
- Dashboard display: The user is redirected to the dashboard where they see:
- Their Auth Token (displayed once at creation, stored as hash).
- Their assigned domains.
- Setup instructions.
- Token Generation: Cryptographically secure random string (256 bits), generated once at registration using
crypto/rand. - Persistence:
- Server-side: Token hash (SHA256) stored in database. Plain token shown to user only once.
- Client-side: User runs
gopublic auth <token>. The client saves this token to~/.gopublic.
- Authorization: Every tunnel connection handshake includes this token. The server validates ownership of requested subdomains against this token.
- Signed Cookies: User sessions use HMAC-signed cookies via
gorilla/securecookie. - CSRF Protection: Double-submit cookie pattern for state-changing operations.
- Cookie Attributes:
HttpOnly,SameSite=Lax,Secure(in production).
- Control Plane: TCP connection on port
:4443. - Multiplexing: Uses
yamuxover the single TCP connection. - Security: TLS for Control Plane is required.
- Connect: Client initiates TCP connection to Server.
- Handshake (Stream 1):
- Client sends
AuthRequest(Token). - Server verifies token.
- Client sends
TunnelRequest(List of Requested Domains + Local Ports). - Server verifies user owns these domains.
- Server responds with
InitResponse.
- Client sends
- Data Transfer:
- Incoming public request -> Server -> Selects Session -> New Yamux Stream -> Client.
- Client reads Stream -> Proxies to Localhost Port based on mapping.
- Frontend: Serve Web Dashboard (React/HTML) and handle OAuth callback.
- Public Ingress: Listen on
:80(HTTP) and:443(HTTPS). - Certificate Management: Automatic Let's Encrypt certificates (Wildcard
*.gopublic.compreferred, or On-Demand). - Tunnel Registry: In-memory map of
Hostname -> Session.
Minimal database (SQLite) required for:
- Users (TelegramID, FirstName, LastName, Username, PhotoURL, CreatedAt)
- Tokens (UserID, TokenString, TokenHash)
- Domains (UserID, SubdomainName)
gopublic auth <token>: Saves token to~/.gopublicconfig file.gopublic start [port]: Start single tunnel to specified port.gopublic start: Readsgopublic.yamlin current dir and starts tunnels.gopublic start --all: Start all defined tunnels fromgopublic.yaml.
- Tunnels automatically reconnect on connection failure.
- Exponential backoff: 1s → 2s → 4s → ... → 60s max.
- Graceful shutdown on SIGINT/SIGTERM.
The client supports "Projects" via YAML files. A user can map their assigned domains to different local services.
version: "1"
tunnels:
# Map 'misty-river' (assigned domain) to local React app
frontend:
proto: http
addr: 3000
subdomain: misty-river
# Map 'silent-star' (assigned domain) to local API
backend:
proto: http
addr: 8080
subdomain: silent-starDuplicate the "Killer Feature" of ngrok.
- Listen Address:
localhost:4040(by default). - Web Interface:
- Traffic Log: Real-time list of all incoming requests (Method, Path, Status, Duration).
- Detail View: Click a request to see full Headers, Body (JSON/Text), and Response.
- Replay: Button to "Replay" a selected request against the local server without resending from the internet.
- Token Secrecy: Tokens allow anyone to host on user's domains. Tokens are hashed (SHA256) before storage.
- Domain Verification: Server MUST enforce that a token can only bind subdomains assigned to that user.
- Session Security: Signed cookies with HMAC, HttpOnly and SameSite attributes.
- CSRF Protection: Double-submit cookie pattern for dashboard operations.
- TLS: Control plane uses TLS in production; Let's Encrypt for automatic certificates.
Language: Golang Соблюдать принципы KISS и DRY при разработке. Действовать как senior golang backend developer Для базы данных использовать sqlite Если для требуемого функционала есть готовая библиотека, то использовать её.
Ключевые библиотеки: Мультиплексирование: github.com/hashicorp/yamux Зачем: Ngrok работает через один постоянный TCP-канал между клиентом и сервером. Чтобы пробрасывать через него много одновременных HTTP-запросов, не открывая новые соединения, нужно мультиплексирование.
CLI: github.com/spf13/cobra. Стандарт для создания CLI-интерфейсов.
HTTP/Routing: github.com/gin-gonic/gin для обработки входящих HTTP-запросов на сервере.