gproxy

package
v0.1.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 3, 2026 License: Apache-2.0 Imports: 21 Imported by: 0

Documentation

Overview

Package gproxy implements a gnet-based event-driven MTProxy server.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func IsUnixSocket added in v0.1.4

func IsUnixSocket(addr string) bool

IsUnixSocket returns true if the bind address is a Unix socket.

func Run

func Run(cfg *Config, logger Logger) (shutdown func(), errCh <-chan error)

Run starts the proxy with graceful shutdown support using gnet. Returns a shutdown function that can be called to stop the server.

Types

type Config

type Config struct {
	// Secrets is the list of allowed proxy secrets.
	Secrets []Secret
	Host    string // Default SNI hostname (from first secret)

	// Network
	BindAddr string

	// TLS Fronting
	MaskHost           string // Domain to mimic (SNI validation, proxy links)
	MaskPort           int    // Default port
	FetchRealCert      bool
	SpliceUnrecognized bool
	CertRefreshHours   int

	// Certificate fetching (where to connect to get real cert)
	// Defaults to MaskHost:MaskPort if not set
	CertHost string
	CertPort int

	// Splice target (where to forward unrecognized clients)
	// Defaults to MaskHost:MaskPort if not set
	SpliceHost          string
	SplicePort          int
	SpliceProxyProtocol int // 0 = off, 1 = v1 (text), 2 = v2 (binary)

	// Performance
	IPPreference      dc.IPPreference
	IdleTimeout       time.Duration
	TimeSkewTolerance time.Duration

	// Upstream (DC connection)
	Socks5Addr string // SOCKS5 proxy for DC connections (e.g., "127.0.0.1:1080")

	// Incoming connection handling
	ProxyProtocol       bool // Accept incoming PROXY protocol headers
	MaxConnectionsPerIP int  // Per IP+secret limit, 0 = unlimited

	// gnet-specific
	Multicore    bool // Use multiple event loops
	ReusePort    bool // Enable SO_REUSEPORT
	LockOSThread bool // Lock goroutines to OS threads
	NumEventLoop int  // Number of event loops (0 = auto)
}

Config configures the gnet proxy server.

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns sensible defaults.

type ConnContext

type ConnContext struct {
	// contains filtered or unexported fields
}

ConnContext holds per-connection state for the gnet event handler.

func NewConnContext

func NewConnContext() *ConnContext

NewConnContext creates a new connection context.

func (*ConnContext) ID added in v0.1.4

func (c *ConnContext) ID() uint64

ID returns the connection ID.

func (*ConnContext) LogPrefix added in v0.1.4

func (c *ConnContext) LogPrefix() string

LogPrefix returns a log prefix like "#123" or "#123:user1".

func (*ConnContext) RealClientAddr added in v0.1.4

func (c *ConnContext) RealClientAddr(fallback net.Addr) net.Addr

RealClientAddr returns the real client address from PROXY protocol. Falls back to the provided gnet connection's remote address if not set.

func (*ConnContext) Relay

func (c *ConnContext) Relay() *RelayContext

Relay returns the relay context (lock-free, may be nil).

func (*ConnContext) SetRealClientAddr added in v0.1.4

func (c *ConnContext) SetRealClientAddr(addr net.Addr)

SetRealClientAddr sets the real client address from PROXY protocol.

func (*ConnContext) SetRelay

func (c *ConnContext) SetRelay(r *RelayContext)

SetRelay sets the relay context and transitions to relay state.

func (*ConnContext) SetSpliceConn added in v0.1.2

func (c *ConnContext) SetSpliceConn(conn net.Conn)

SetSpliceConn sets the splice connection.

func (*ConnContext) SetState

func (c *ConnContext) SetState(state ConnState)

SetState sets the connection state (lock-free).

func (*ConnContext) SpliceConn added in v0.1.2

func (c *ConnContext) SpliceConn() net.Conn

SpliceConn returns the splice connection (lock-free, may be nil).

func (*ConnContext) State

func (c *ConnContext) State() ConnState

State returns the current connection state (lock-free).

type ConnLimiter added in v0.1.4

type ConnLimiter struct {
	// contains filtered or unexported fields
}

ConnLimiter limits concurrent connections per IP+secret combination. Uses sharded maps and atomic counters for minimal contention.

func NewConnLimiter added in v0.1.4

func NewConnLimiter(maxConns int) *ConnLimiter

NewConnLimiter creates a new connection limiter. maxConns <= 0 disables limiting.

func (*ConnLimiter) ActiveConnections added in v0.1.4

func (l *ConnLimiter) ActiveConnections() int64

ActiveConnections returns the total number of active connections being tracked. This is O(n) and should only be used for metrics, not in hot path.

func (*ConnLimiter) Release added in v0.1.4

func (l *ConnLimiter) Release(key string)

Release releases a connection slot. key must be the value returned by TryAcquire.

func (*ConnLimiter) TryAcquire added in v0.1.4

func (l *ConnLimiter) TryAcquire(ip net.IP, secret []byte) (key string, ok bool)

TryAcquire attempts to acquire a connection slot for the given IP+secret. Returns the key (for Release) and success status. If maxConns is 0, always succeeds (limiting disabled).

type ConnState

type ConnState int32

ConnState represents the current state of a client connection.

const (
	StateReadProxyProto ConnState = iota // Need PROXY protocol header (optional)
	StateReadTLSHeader                   // Need 5 bytes for TLS record header
	StateReadTLSPayload                  // Need header.length bytes for payload
	StateReadO2Frame                     // Need 64 bytes for obfuscated2 frame
	StateDialingDC                       // Async dial in progress
	StateRelaying                        // Bidirectional relay active
	StateSplicing                        // Forward to mask host (invalid client)
	StateClosed                          // Connection is closing
)

func (ConnState) String

func (s ConnState) String() string

String returns the state name for debugging.

type DCConnContext added in v0.1.2

type DCConnContext struct {
	// Link back to client connection
	ClientConn gnet.Conn

	// Client context for state access
	ClientCtx *ConnContext

	// DC ciphers (proxy <-> DC)
	DCEncrypt cipher.Stream
	DCDecrypt cipher.Stream

	// Client ciphers (cached from relay context)
	ClientEncrypt cipher.Stream // encrypt TO client
}

DCConnContext holds per-DC-connection state.

type Logger

type Logger interface {
	Debug(format string, args ...any)
	Info(format string, args ...any)
	Warn(format string, args ...any)
	Error(format string, args ...any)
}

Logger interface for proxy logging.

type ProxyHandler

type ProxyHandler struct {
	gnet.BuiltinEventEngine
	// contains filtered or unexported fields
}

ProxyHandler implements gnet.EventHandler for the MTProxy server.

func NewProxyHandler

func NewProxyHandler(cfg *Config, logger Logger) *ProxyHandler

NewProxyHandler creates a new gnet proxy handler.

func (*ProxyHandler) OnBoot

func (h *ProxyHandler) OnBoot(eng gnet.Engine) gnet.Action

OnBoot is called when the gnet engine starts.

func (*ProxyHandler) OnClose

func (h *ProxyHandler) OnClose(c gnet.Conn, err error) gnet.Action

OnClose is called when a connection is closed.

func (*ProxyHandler) OnOpen

func (h *ProxyHandler) OnOpen(c gnet.Conn) ([]byte, gnet.Action)

OnOpen is called when a new connection is accepted.

func (*ProxyHandler) OnShutdown

func (h *ProxyHandler) OnShutdown(eng gnet.Engine)

OnShutdown is called when the gnet engine shuts down.

func (*ProxyHandler) OnTraffic

func (h *ProxyHandler) OnTraffic(c gnet.Conn) gnet.Action

OnTraffic is called when data is available to read.

type ProxyProtoResult added in v0.1.4

type ProxyProtoResult struct {
	SrcAddr   net.Addr // Source (client) address
	DstAddr   net.Addr // Destination (server) address
	HeaderLen int      // Total bytes consumed by header
	IsLocal   bool     // True if LOCAL command (health check)
}

ProxyProtoResult holds the parsed PROXY protocol header result.

func ParseProxyProtocol added in v0.1.4

func ParseProxyProtocol(data []byte) (*ProxyProtoResult, error)

ParseProxyProtocol attempts to parse a PROXY protocol v1 or v2 header. Returns nil if the data doesn't start with a valid PROXY protocol header. Returns error if header is malformed or incomplete.

type RelayContext

type RelayContext struct {
	// Client ciphers (client <-> proxy)
	Encryptor cipher.Stream // encrypt data TO client
	Decryptor cipher.Stream // decrypt data FROM client

	// DC connection and ciphers (proxy <-> DC)
	DCConn    gnet.Conn     // gnet connection to Telegram DC (enrolled in dcClient)
	DCEncrypt cipher.Stream // encrypt data TO DC
	DCDecrypt cipher.Stream // decrypt data FROM DC
}

RelayContext holds immutable relay state set once after handshake. Read without locking via atomic pointer.

type ReplayCache

type ReplayCache struct {
	// contains filtered or unexported fields
}

ReplayCache detects replay attacks by tracking seen session IDs. Uses striped locking (32 shards) to reduce contention under high load.

func NewReplayCache

func NewReplayCache(maxSize int, ttl time.Duration) *ReplayCache

NewReplayCache creates a new replay cache.

func (*ReplayCache) Seen

func (c *ReplayCache) Seen(sessionID []byte) bool

Seen checks if the session ID was seen before. Returns true if this is a replay, false if new.

type Secret

type Secret struct {
	Name   string // User-friendly name for logging
	Key    []byte // 16-byte secret key
	Host   string // SNI hostname
	RawHex string // Original hex string for link generation
}

Secret represents a named proxy secret.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL