Documentation
¶
Overview ¶
Package webproxy implements Telegram WEB proxy capabilities, shared frames, serialized HTTPS sessions, and fixed-backend stream relaying.
Index ¶
- Constants
- Variables
- func AppendFrame(dst []byte, frame Frame) ([]byte, error)
- func EncodeFrame(frame Frame) ([]byte, error)
- func ParseHello(input []byte) error
- func ValidateBasePath(basePath string) error
- func ValidateClientFrame(frame Frame) error
- func ValidateFrame(frame Frame, direction Direction) error
- func ValidateHostname(hostname string) error
- func ValidateLocalBackend(address string) error
- func WindowDelta(payload []byte) (uint32, error)
- func WindowPayload(delta uint32) ([]byte, error)
- type Backend
- type BackendBudget
- type BackendDialContextFunc
- type BackendFactory
- type BackendOpenOptions
- type BootstrapAuthorization
- type BridgeFailure
- type BridgePage
- type Capability
- type Capacity
- type CarrierMode
- type CreateResult
- type DialContextFunc
- type Direction
- type Frame
- type FrameType
- type HTTPServer
- type HTTPServerConfig
- type Limits
- type Manager
- func (m *Manager) AuthenticateBootstrap(token string) (*BootstrapAuthorization, error)
- func (m *Manager) Capacity() Capacity
- func (m *Manager) CarrierMode() CarrierMode
- func (m *Manager) Close(token string) error
- func (m *Manager) Create(token, clientIP string, body []byte) (CreateResult, error)
- func (m *Manager) Get(token string) (*Session, error)
- func (m *Manager) IssueBootstrap(capability Capability, clientIP string) (string, error)
- func (m *Manager) MatchCapability(capability Capability) (Profile, bool)
- func (m *Manager) RuntimeStats() RuntimeStats
- func (m *Manager) Shutdown(ctx context.Context) error
- type ManagerConfig
- type PollLease
- type Profile
- type RuntimeCounter
- type RuntimeStats
- type SecretMode
- type Session
- func (s *Session) AcquireWebSocket() bool
- func (s *Session) AcquireWebSocketLane(laneID uint32) *WebSocketLaneLease
- func (s *Session) CarrierMode() CarrierMode
- func (s *Session) Close()
- func (s *Session) LastActivity() time.Time
- func (s *Session) Poll(ctx context.Context, cursor uint64) ([]byte, uint64, error)
- func (s *Session) PollCarrier(ctx context.Context, cursor uint64) ([]byte, uint64, *PollLease, error)
- func (s *Session) PollCarrierLane(ctx context.Context, laneID uint32, cursor uint64) ([]byte, uint64, bool, *PollLease, error)
- func (s *Session) PollLane(ctx context.Context, laneID uint32, cursor uint64) ([]byte, uint64, bool, error)
- func (s *Session) ProcessUp(sequence uint64, body []byte) (uint64, error)
- func (s *Session) ProcessUpLane(laneID uint32, sequence uint64, body []byte) (uint64, error)
- func (s *Session) Profile() Profile
- type Timeouts
- type WebSocketClose
- type WebSocketLaneLease
- func (l *WebSocketLaneLease) Poll(ctx context.Context, cursor uint64) ([]byte, uint64, bool, error)
- func (l *WebSocketLaneLease) PollCarrier(ctx context.Context, cursor uint64) ([]byte, uint64, bool, *PollLease, error)
- func (l *WebSocketLaneLease) ProcessUp(sequence uint64, body []byte) (uint64, error)
- func (l *WebSocketLaneLease) Release()
Constants ¶
const ( FrameHeaderSize = 8 MaxFramePayload = 1024 * 1024 MaxBatchFrames = 4096 MaxStreamID = 0xFFFFFF InitialStreamWindow = 4 * 1024 * 1024 RelayDataChunk = 64 * 1024 )
const ( // FallbackClassificationHeader marks which exact Nginx fallback contract // applies to an internal sentinel response. FallbackClassificationHeader = "X-Telego-Fallback" FallbackOrdinarySite = "ordinary-site-v1" FallbackSanitizedPublic = "sanitized-public-v1" // NginxPassthroughFallback is the exact Phase 5 contract for ordinary site // traffic. The named location must preserve the original method, complete // request URI (including args), body, Cookie, and all site request headers. NginxPassthroughFallback = "" /* 475-byte string literal not displayed */ // NginxSanitizedFallback is the exact Phase 5 contract for carrier-shaped // traffic that did not authenticate. The named location must force GET; use // $uri (never $request_uri) so args are empty; disable the request body; and // clear every listed carrier credential/header before proxying. NginxSanitizedFallback = "" /* 447-byte string literal not displayed */ )
const PermissionsPolicy = "" /* 408-byte string literal not displayed */
PermissionsPolicy disables browser features that the HTTPS bridge does not use. It is intentionally exported so an integrating TLS terminator can test that it preserves the header unchanged.
Variables ¶
var ( // ErrInvalidHostname reports a hostname that is not the canonical lowercase // ASCII/IDNA form required by the WEB proxy protocol. ErrInvalidHostname = errors.New("invalid WEB proxy hostname") // ErrInvalidSecret reports a secret that is neither a 16-byte base secret nor // the same secret with the WEB-compatible dd prefix. ErrInvalidSecret = errors.New("invalid WEB proxy secret") // ErrInvalidCapability reports a non-canonical bridge capability string. ErrInvalidCapability = errors.New("invalid WEB proxy capability") )
var ( ErrEmptyFrameBatch = errors.New("empty WEB frame batch") ErrIncompleteFrame = errors.New("incomplete WEB frame") ErrTooManyFrames = errors.New("WEB frame batch contains too many frames") ErrPayloadTooLarge = errors.New("WEB frame payload exceeds limit") ErrInvalidFrame = errors.New("invalid WEB frame") )
var ( ErrInvalidHTTPServerConfig = errors.New("invalid WEB HTTP server configuration") ErrHTTPServerStarted = errors.New("WEB HTTP server already started") )
var ( ErrAuthentication = errors.New("WEB authentication failed") ErrBackpressure = errors.New("WEB temporary backpressure") ErrLimit = errors.New("WEB resource limit reached") ErrProtocol = errors.New("WEB protocol error") ErrClosed = errors.New("WEB session closed") )
var ErrInvalidManagerConfig = errors.New("invalid WEB session manager configuration")
Functions ¶
func AppendFrame ¶
AppendFrame appends one shape-valid frame to dst.
func EncodeFrame ¶
EncodeFrame encodes one shape-valid frame.
func ParseHello ¶
ParseHello accepts exactly one v1 HELLO frame and no other bytes.
func ValidateBasePath ¶ added in v0.6.8
ValidateBasePath rejects aliases instead of normalizing a credential scope.
func ValidateClientFrame ¶
ValidateClientFrame validates a normal authenticated uplink frame. HELLO is excluded because it is valid only as the standalone session-creation body accepted by ParseHello.
func ValidateFrame ¶
ValidateFrame checks both the frame's exact shape and whether its type is valid in the supplied direction.
func ValidateHostname ¶
ValidateHostname requires the already-canonical hostname spelling used in capability derivation. It deliberately does not trim, lowercase, or convert Unicode input because doing so would silently derive a different URL than the configured value.
func ValidateLocalBackend ¶ added in v0.6.1
ValidateLocalBackend checks an explicit numeric loopback TCP or Unix target.
func WindowDelta ¶
WindowDelta decodes a nonzero WINDOW credit delta.
func WindowPayload ¶
WindowPayload encodes a nonzero WINDOW credit delta.
Types ¶
type Backend ¶ added in v0.6.1
Backend is a bounded nonblocking stream. TryRead and TryWrite run on the owner supplied to the factory; zero with no error means temporary pressure. Close may be called from another goroutine and completes through OnClosed.
type BackendBudget ¶ added in v0.6.1
BackendBudget accounts retained capacity and queue metadata. Callbacks are concurrency-safe and must never run while the caller holds a session lock.
type BackendDialContextFunc ¶
type BackendDialContextFunc func(ctx context.Context, network, address, clientIP string) (net.Conn, error)
BackendDialContextFunc opens one WEB backend stream with its validated client IP. Integrations use this seam to prepend a trusted internal PROXY header.
type BackendFactory ¶ added in v0.6.1
type BackendFactory func(BackendOpenOptions) (Backend, error)
func GnetBackendFactory ¶ added in v0.6.1
func GnetBackendFactory(dial BackendDialContextFunc) BackendFactory
GnetBackendFactory keeps explicit TCP/Unix backend overrides on the WEB stream owner. The supplied dialer runs only during bounded establishment; enrolled sockets never have blocking relay readers or writers.
type BackendOpenOptions ¶ added in v0.6.1
type BackendOpenOptions struct {
Context context.Context
Owner gnet.EventLoop
ClientIP string
Network, Address string
MaxInputBytes, MaxOutputBytes int
MaxInputItems, MaxOutputItems int
InputBudget, OutputBudget BackendBudget
Notify func()
OnOpened func(error)
OnClosed func(error)
}
BackendOpenOptions gives each stream a stable owner and bounded queues. Notify schedules further work; OnOpened and OnClosed each run exactly once. OnClosed runs after owner cleanup and every budget release has completed.
type BootstrapAuthorization ¶
type BootstrapAuthorization struct {
// contains filtered or unexported fields
}
BootstrapAuthorization is an opaque, short-lived proof that a bootstrap bearer authenticated before its request body was read. Create revalidates the bootstrap under the manager lock, including expiry and prior idempotent use.
func (*BootstrapAuthorization) Create ¶
func (a *BootstrapAuthorization) Create(clientIP string, body []byte) (CreateResult, error)
Create parses HELLO only after bootstrap authentication, then atomically creates or retries the session.
func (*BootstrapAuthorization) GoString ¶
func (*BootstrapAuthorization) GoString() string
func (*BootstrapAuthorization) String ¶
func (*BootstrapAuthorization) String() string
type BridgeFailure ¶ added in v0.6.6
type BridgeFailure struct {
BridgeID uint64 `json:"-"`
Suppressed uint64 `json:"-"`
User string `json:"-"`
Carrier CarrierMode `json:"-"`
Delivery string `json:"-"`
Reason string `json:"reason"`
Error string `json:"error"`
LaneID uint32 `json:"lane_id"`
CloseCode uint16 `json:"close_code"`
ReadyState uint8 `json:"ready_state"`
HTTPStatus uint16 `json:"http_status"`
ElapsedMS uint64 `json:"elapsed_ms"`
OperationMS uint64 `json:"operation_ms"`
QueuedBytes uint64 `json:"queued_bytes"`
QueuedItems uint32 `json:"queued_items"`
BufferedBytes uint64 `json:"buffered_bytes"`
WasClean bool `json:"was_clean,omitzero"`
}
BridgeFailure contains client-reported diagnostics, never exception text, URLs, credentials, frame contents, or WebSocket close reason strings.
func (BridgeFailure) IsLaneClosure ¶ added in v0.6.6
func (f BridgeFailure) IsLaneClosure() bool
type BridgePage ¶
BridgePage is one self-contained, per-request HTTPS carrier document.
func RenderBridge ¶
func RenderBridge(hostname, bootstrapToken string, batchBytes int) (BridgePage, error)
RenderBridge constructs the backward-compatible serialized HTTPS bridge.
func RenderBridgeForCarrier ¶ added in v0.5.2
func RenderBridgeForCarrier( hostname string, bootstrapToken string, batchBytes int, carrier CarrierMode, ) (BridgePage, error)
RenderBridgeForCarrier constructs one WEB bridge for the selected carrier. The bootstrap token exists only in this no-store response, never in a URL.
type Capability ¶
Capability is the binary HMAC-SHA256 bridge capability.
func DeriveCapability ¶
func DeriveCapability(hostname string, secret []byte) (Capability, error)
DeriveCapability derives a bridge capability from a canonical hostname and a decoded 16-byte plain or 17-byte dd-prefixed secret.
func DeriveCapabilityForPath ¶ added in v0.6.8
func DeriveCapabilityForPath(hostname, basePath string, secret []byte) (Capability, error)
DeriveCapabilityForPath uses v1 at the root and v2 for a nonempty base path.
func ParseCapability ¶
func ParseCapability(value string) (Capability, error)
ParseCapability decodes one canonical 43-character unpadded base64url capability.
func (Capability) Equal ¶
func (c Capability) Equal(other Capability) bool
Equal compares two capabilities in constant time.
func (Capability) String ¶
func (c Capability) String() string
String returns the canonical unpadded base64url representation.
type Capacity ¶
type Capacity struct {
Bootstraps int
Sessions int
ClosedTokens int
Streams int
BackendDials int
PendingBytes int64
PendingItems int64
}
Capacity is a point-in-time view of the manager's bounded resources.
type CarrierMode ¶ added in v0.5.2
type CarrierMode string
CarrierMode selects the HTTP transport for one WEB relay session.
const ( CarrierHTTPS CarrierMode = "https" CarrierHTTPSLanes CarrierMode = "https-lanes" CarrierWebSocket CarrierMode = "websocket" CarrierWebSocketLanes CarrierMode = "websocket-lanes" )
func ParseCarrierMode ¶ added in v0.5.2
func ParseCarrierMode(value string) (CarrierMode, error)
ParseCarrierMode returns a supported carrier mode. An empty value preserves the serialized HTTPS mode used before carrier selection was configurable.
type CreateResult ¶
CreateResult is the idempotent HELLO/WELCOME session exchange.
type DialContextFunc ¶
DialContextFunc opens the fixed backend connection for one WEB stream.
type Frame ¶
Frame is one complete WEB shared frame. Payload returned by ParseBatch aliases the input buffer and must not outlive or mutate independently from it.
func ParseBatch ¶
ParseBatch parses and shape-validates one nonempty frame batch. Payload slices in the result alias input.
type HTTPServer ¶
type HTTPServer struct {
// contains filtered or unexported fields
}
HTTPServer is an independent gnet engine for HTTPS WEB carriers. Constructing it has no listener or process-global side effects.
func NewHTTPServer ¶
func NewHTTPServer(config HTTPServerConfig) (*HTTPServer, error)
NewHTTPServer validates a WEB HTTP engine without starting it.
func (*HTTPServer) Errors ¶
func (s *HTTPServer) Errors() <-chan error
Errors reports an unexpected gnet exit and then closes. A normal Stop closes the channel without sending a value.
type HTTPServerConfig ¶
type HTTPServerConfig struct {
// OnBridgeFailure receives one failure plus bounded lane-close reports per bridge.
OnBridgeFailure func(BridgeFailure)
OnWebSocketClose func(WebSocketClose)
Bind string
Hostname string
BasePath string
Manager *Manager
PassthroughStatus int
SanitizedFallbackStatus int
Multicore bool
ReusePort bool
LockOSThread bool
NumEventLoop int
SocketSendBuffer int
HeaderTimeout time.Duration
BodyTimeout time.Duration
IdleTimeout time.Duration
WriteTimeout time.Duration
TrustedProxyCIDRs []string
// contains filtered or unexported fields
}
HTTPServerConfig configures the private HTTP/1.1 origin placed behind the deployment's TLS-terminating Nginx. It does not alter the public MTProxy gnet engine or own Manager shutdown.
type Limits ¶
type Limits struct {
CarrierBatchBytes int
MaxBodyBytes int
MaxStreamsPerSession int
MaxClosedStreamIDs int
MaxPendingPerSession int
MaxPendingGlobal int
MaxPendingItemsPerSession int
MaxPendingItemsGlobal int
MaxBootstraps int
MaxSessions int
MaxClosedTokens int
MaxStreams int
MaxBackendDialsInFlight int
}
Limits bounds every resource owned by the serialized HTTPS session manager. Start with DefaultLimits and change only values that an operator needs to tune.
func DefaultLimits ¶
func DefaultLimits() Limits
DefaultLimits returns the protocol reference defaults for serialized HTTPS.
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager owns WEB bootstrap tokens, authenticated sessions, and process-wide stream and queue budgets.
func NewManager ¶
func NewManager(config ManagerConfig) (*Manager, error)
NewManager validates and copies config before starting its expiry worker.
func (*Manager) AuthenticateBootstrap ¶
func (m *Manager) AuthenticateBootstrap(token string) (*BootstrapAuthorization, error)
AuthenticateBootstrap authenticates a canonical bootstrap bearer without reading or parsing a request body. Unknown and malformed bearers return the same authentication error.
func (*Manager) CarrierMode ¶ added in v0.5.2
func (m *Manager) CarrierMode() CarrierMode
CarrierMode returns the transport used for newly created sessions.
func (*Manager) Close ¶
Close terminates the authenticated session. A recently closed valid token is idempotent; an unknown token remains indistinguishable from bad authentication.
func (*Manager) Create ¶
func (m *Manager) Create(token, clientIP string, body []byte) (CreateResult, error)
Create atomically consumes a bootstrap for one exact HELLO body. Retrying the same token and identical body returns the original token and Session pointer. Authentication always completes before body parsing.
func (*Manager) IssueBootstrap ¶
func (m *Manager) IssueBootstrap(capability Capability, clientIP string) (string, error)
IssueBootstrap authenticates a profile capability and issues a canonical two-minute bootstrap bearer.
func (*Manager) MatchCapability ¶
func (m *Manager) MatchCapability(capability Capability) (Profile, bool)
MatchCapability scans the complete profile set and never returns manager-owned profile storage.
func (*Manager) RuntimeStats ¶ added in v0.5.2
func (m *Manager) RuntimeStats() RuntimeStats
RuntimeStats returns WEB diagnostics without bearer or client identifiers.
type ManagerConfig ¶
type ManagerConfig struct {
// DebugDiagnostics enables bounded reconnect diagnostics. Disabled by default.
DebugDiagnostics bool
Profiles []Profile
Backend string
Carrier CarrierMode
Limits Limits
Timeouts Timeouts
DialContext DialContextFunc
BackendDialContext BackendDialContextFunc
BackendFactory BackendFactory
}
ManagerConfig supplies the already-derived WEB profiles and the one local backend accepted for every logical stream. Backend can be numeric loopback TCP or an absolute Unix-socket path, with an optional unix:// prefix.
func DefaultManagerConfig ¶
func DefaultManagerConfig(profiles []Profile, backend string) ManagerConfig
DefaultManagerConfig constructs a complete configuration using the protocol reference limits and the standard library TCP dialer.
type PollLease ¶
type PollLease struct {
// contains filtered or unexported fields
}
PollLease keeps one completed carrier response as the active downlink poll until the HTTP layer has drained that response. A newer poll supersedes it.
func (*PollLease) Release ¶
func (l *PollLease) Release()
Release ends this response's claim if it is still the newest poll.
func (*PollLease) Superseded ¶
Superseded reports whether a newer downlink poll replaced this response.
type Profile ¶
type Profile struct {
// contains filtered or unexported fields
}
Profile is one immutable WEB credential derived from a named Telego secret. A single 16-byte base secret produces a plain profile and a dd profile.
func DeriveProfiles ¶
DeriveProfiles creates the plain and dd WEB credentials for an existing Telego 16-byte base secret. The returned order is always plain, then dd.
func DeriveProfilesForPath ¶ added in v0.6.8
DeriveProfilesForPath binds both credentials to one canonical WEB base path.
func (Profile) Capability ¶
func (p Profile) Capability() Capability
func (Profile) Mode ¶
func (p Profile) Mode() SecretMode
func (Profile) SecretBytes ¶
SecretBytes returns a copy of the decoded credential, including the leading dd byte for a SecretDD profile.
type RuntimeCounter ¶ added in v0.5.2
RuntimeCounter is one labeled cumulative WEB counter.
type RuntimeStats ¶ added in v0.5.2
type RuntimeStats struct {
Capacity Capacity
WebSocketsActive int64
SessionsCreated uint64
SessionsClosed []RuntimeCounter
CarrierRetries []RuntimeCounter
Backpressure []RuntimeCounter
}
RuntimeStats is a point-in-time view of WEB capacity and cumulative events.
type SecretMode ¶
type SecretMode uint8
SecretMode identifies the MTProxy secret spelling used to derive a WEB profile capability.
const ( SecretPlain SecretMode = iota SecretDD )
func (SecretMode) String ¶
func (m SecretMode) String() string
type Session ¶
type Session struct {
// contains filtered or unexported fields
}
Session is one authenticated HTTPS carrier session. The serialized carrier permits one uplink and downlink. The lanes carrier permits one pair per lane.
func (*Session) AcquireWebSocket ¶ added in v0.5.3
AcquireWebSocket reserves the single multiplexed WebSocket for this session.
func (*Session) AcquireWebSocketLane ¶ added in v0.5.3
func (s *Session) AcquireWebSocketLane(laneID uint32) *WebSocketLaneLease
AcquireWebSocketLane reserves one nonzero stream lane for a WebSocket.
func (*Session) CarrierMode ¶ added in v0.5.2
func (s *Session) CarrierMode() CarrierMode
CarrierMode returns the immutable transport selected for this session.
func (*Session) Close ¶
func (s *Session) Close()
Close aborts all logical streams and wakes parked carrier operations.
func (*Session) LastActivity ¶
LastActivity returns the last carrier activity used for reconnect expiry.
func (*Session) Poll ¶
Poll acknowledges cursor, replays any unacknowledged batch, or waits for the next batch. Direct callers release the response claim before Poll returns.
func (*Session) PollCarrier ¶
func (s *Session) PollCarrier(ctx context.Context, cursor uint64) ([]byte, uint64, *PollLease, error)
PollCarrier retains the newest-poll claim until the returned lease is released by the carrier after its HTTP response drains.
func (*Session) PollCarrierLane ¶ added in v0.5.2
func (s *Session) PollCarrierLane( ctx context.Context, laneID uint32, cursor uint64, ) ([]byte, uint64, bool, *PollLease, error)
PollCarrierLane retains the per-lane response claim until HTTP drains it.
func (*Session) PollLane ¶ added in v0.5.2
func (s *Session) PollLane(ctx context.Context, laneID uint32, cursor uint64) ([]byte, uint64, bool, error)
PollLane acknowledges and polls one independent stream lane.
func (*Session) ProcessUp ¶
ProcessUp applies the next serialized uplink batch or acknowledges a byte-identical retry of the last committed sequence.
func (*Session) ProcessUpLane ¶ added in v0.5.2
ProcessUpLane applies one uplink batch to an independent stream lane.
type Timeouts ¶
type Timeouts struct {
BackendDial time.Duration
LongPoll time.Duration
ReconnectGrace time.Duration
BootstrapLifetime time.Duration
}
Timeouts controls backend establishment, long polling, and disconnected session retention.
func DefaultTimeouts ¶
func DefaultTimeouts() Timeouts
DefaultTimeouts returns the protocol reference defaults.
type WebSocketClose ¶ added in v0.6.6
type WebSocketClose struct {
User string
Carrier CarrierMode
BridgeID uint64
LaneID uint32
Reason string
StreamOrigin string
ErrorCategory string
CloseCode uint16
PeerCloseCode uint16
AgeMS int64
ReceivedBytes uint64
SentBytes uint64
Suppressed uint64
}
WebSocketClose describes an observed server-side close. It contains no addresses, tokens, payloads, or peer-supplied reason text.
type WebSocketLaneLease ¶ added in v0.5.3
type WebSocketLaneLease struct {
// contains filtered or unexported fields
}
WebSocketLaneLease owns one WebSocket-lanes attachment. Its identity keeps stale cleanup from affecting a later attachment that reuses the same ID.
func (*WebSocketLaneLease) Poll ¶ added in v0.5.3
func (l *WebSocketLaneLease) Poll( ctx context.Context, cursor uint64, ) ([]byte, uint64, bool, error)
Poll acknowledges and polls downlink through this acquired lane.
func (*WebSocketLaneLease) PollCarrier ¶ added in v0.5.3
func (l *WebSocketLaneLease) PollCarrier( ctx context.Context, cursor uint64, ) ([]byte, uint64, bool, *PollLease, error)
PollCarrier retains the downlink claim until the caller releases it.
func (*WebSocketLaneLease) ProcessUp ¶ added in v0.5.3
func (l *WebSocketLaneLease) ProcessUp(sequence uint64, body []byte) (uint64, error)
ProcessUp applies one uplink message through this acquired lane.
func (*WebSocketLaneLease) Release ¶ added in v0.5.3
func (l *WebSocketLaneLease) Release()
Release idempotently detaches this lane and closes only its backend stream.
Source Files
¶
- backend.go
- backend_budget.go
- backend_gnet.go
- backend_pump.go
- bridge.go
- bridge_diagnostics.go
- bridge_recovery.go
- capability.go
- carrier.go
- doc.go
- frame.go
- http_parser.go
- http_server.go
- manager.go
- recovery.go
- runtime_stats.go
- session.go
- session_config.go
- stream_history.go
- websocket_codec.go
- websocket_diagnostics.go
- websocket_handshake.go
- websocket_transport.go