session

package
v1.2.0 Latest Latest
Warning

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

Go to latest
Published: Apr 20, 2026 License: MPL-2.0 Imports: 18 Imported by: 0

Documentation

Overview

Package session implements the Ghost Constant Bitrate (CBR) Engine. Ghost achieves statistical undetectability by enforcing an isochronous transmission schedule with fixed-size frames, masking application traffic patterns from DPI/statistical analysis.

Package session — session manager for multiple concurrent sessions. The Manager tracks active sessions, handles incoming connections, and enforces per-client policies.

Package session — key rotation (rekey) logic.

Rekey is triggered either by time (configurable interval) or by volume (bytes sent threshold). It derives new keys from the current session key material, providing forward secrecy within a session.

IMPORTANT: Only one side (the client) initiates rekey. The server only responds to incoming REKEY frames. Both sides must derive from the SAME base key material — the initiator's EncryptKey, which is the receiver's DecryptKey.

Package session implements the HiVoid session layer.

A Session ties together:

  • A QUIC connection
  • Hybrid key exchange state
  • Per-direction AEAD ciphers
  • Frame read/write with nonce tracking
  • Key rotation (rekey) scheduling
  • Proxy tunnel dial/accept for system traffic forwarding

Package session — TunnelConn implements net.Conn over an encrypted QUIC stream.

TunnelConn provides the pipe between an OS-level TCP connection (from the local SOCKS5/HTTP proxy) and a QUIC stream to the HiVoid server. Every Write call encrypts data with the session's AEAD cipher using a random nonce, and every Read call decrypts an incoming frame.

Frame format on the tunnel stream (FrameData):

[Header: 6B][Nonce: 12B][Ciphertext: N+16B]

where N is the plaintext length and 16 is the AEAD auth tag.

Index

Constants

View Source
const (
	// GhostDefaultFrameSize is the MTU-optimized payload size for all frames.
	GhostDefaultFrameSize = 1024

	// GhostMaxQueueSize bounds memory usage under congestion.
	GhostMaxQueueSize = 2048
)

Variables

View Source
var (
	ErrHandshakeTimeout = errors.New("handshake timeout (probing?)")
	ErrInvalidFrame     = errors.New("invalid protocol frame")
)

Functions

func ObfsConfigForName added in v0.2.0

func ObfsConfigForName(name string) obfuscation.Config

ObfsConfigForName maps a config string to concrete obfuscation parameters.

func ObfsConfigToName added in v0.6.0

func ObfsConfigToName(cfg obfuscation.Config) string

ObfsConfigToName maps an obfuscation config back to its name.

func ObfsNameToID added in v0.6.0

func ObfsNameToID(name string) uint8

ObfsNameToID converts an obfuscation config string to its wire ID for ClientHello.

func SendProxyErrToStream

func SendProxyErrToStream(stream *quic.Stream, msg string)

SendProxyErrToStream writes a failure ProxyResponse to the stream.

func SendProxyError added in v0.7.0

func SendProxyError(stream *quic.Stream, msg string) error

SendProxyError writes a failure proxy response to the stream.

func SendProxyOK

func SendProxyOK(stream *quic.Stream) error

SendProxyOK writes a successful proxy response to the stream.

func SendProxyOkToStream

func SendProxyOkToStream(stream *quic.Stream) error

SendProxyOkToStream writes a success ProxyResponse directly to the stream. This is called by the server forwarder before entering data relay mode.

Types

type Config

type Config struct {
	RekeyInterval time.Duration
	RekeyBytes    int64
	IsClient      bool
	Engine        *intelligence.Engine
	ObfsConfig    obfuscation.Config

	// UUID is the 16-byte client identity sent in ClientHello (client side only).
	// Leave zero to send an anonymous connection.
	UUID [16]byte

	// AllowedUUIDs is the server-side allowlist. If non-empty, clients whose
	// UUID is not in the list are rejected during handshake.
	AllowedUUIDs [][16]byte

	// ClientMode is the mode the client wants to use (client side only).
	ClientMode uint8
	// ClientObfs is the obfuscation type the client wants to use (client side only).
	ClientObfs uint8
}

Config holds session configuration options.

func DefaultConfig

func DefaultConfig(isClient bool) Config

DefaultConfig returns production-ready session defaults.

type ID

type ID [16]byte

ID is a 16-byte random session identifier.

func GenerateID

func GenerateID() (ID, error)

GenerateID creates a new random session ID.

func (ID) String

func (id ID) String() string

type Manager

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

Manager manages a pool of active HiVoid sessions.

func NewManager

func NewManager(isClient bool, mode intelligence.Mode, logger *zap.Logger) *Manager

NewManager creates a Manager.

func (*Manager) AcceptAndHandshake

func (m *Manager) AcceptAndHandshake(ctx context.Context, conn *quic.Conn) (*Session, error)

AcceptAndHandshake wraps a newly accepted QUIC connection into a Session, performs the server-side handshake, and registers it.

func (*Manager) CloseAll

func (m *Manager) CloseAll()

CloseAll shuts down all managed sessions.

func (*Manager) Count

func (m *Manager) Count() int

Count returns the number of active sessions.

func (*Manager) Dial

func (m *Manager) Dial(ctx context.Context, conn *quic.Conn) (*Session, error)

Dial creates a new client-side session over an established QUIC connection.

func (*Manager) EnforceQuotas added in v0.7.0

func (m *Manager) EnforceQuotas()

func (*Manager) Get

func (m *Manager) Get(id ID) (*Session, bool)

Get retrieves a session by ID.

func (*Manager) GetActiveSnapshots added in v0.11.3

func (m *Manager) GetActiveSnapshots() []SessionSnapshot

GetActiveSnapshots returns a list of current active clients (grouped by UUID and IP).

func (*Manager) GetPoliciesSnapshot added in v1.0.0

func (m *Manager) GetPoliciesSnapshot() map[[16]byte]UserPolicy

GetPoliciesSnapshot returns a copy of all runtime user policies.

func (*Manager) GetPolicy added in v1.0.0

func (m *Manager) GetPolicy(uuid [16]byte) (UserPolicy, bool)

GetPolicy returns the runtime policy for a specific UUID.

func (*Manager) KickAll added in v0.11.3

func (m *Manager) KickAll()

KickAll closes all active sessions with a signal to the client to reconnect. Uses custom error code 0x12 (Reconnect Requested).

func (*Manager) KickUser added in v1.0.0

func (m *Manager) KickUser(uuid [16]byte)

KickUser forcefully closes all active sessions for a specific UUID. Uses custom error code 0x10 to signify policy/limit reached.

func (*Manager) Name added in v0.11.6

func (m *Manager) Name() string

Name returns the manager's name.

func (*Manager) RefreshActiveSessionPolicies added in v0.2.0

func (m *Manager) RefreshActiveSessionPolicies()

RefreshActiveSessionPolicies reapplies user policy mode/obfs to active sessions.

func (*Manager) Remove

func (m *Manager) Remove(id ID)

Remove closes and removes a session.

func (*Manager) SetAllowedUUIDs

func (m *Manager) SetAllowedUUIDs(uuids [][16]byte)

SetAllowedUUIDs configures the server-side UUID allowlist. Connections from clients whose UUID is not in the list will be rejected. Pass nil or an empty slice to allow all clients only when requireKnownPolicy is disabled.

func (*Manager) SetClientParams added in v0.6.0

func (m *Manager) SetClientParams(mode intelligence.Mode, obfsName string)

SetClientParams configures the mode and obfs sent during outbound handshake.

func (*Manager) SetClientUUID

func (m *Manager) SetClientUUID(u [16]byte)

SetClientUUID sets the UUID that will be sent in ClientHello for outbound (client-side) connections. Must be called before Connect/Dial.

func (*Manager) SetMode added in v0.2.0

func (m *Manager) SetMode(mode intelligence.Mode)

SetMode updates the default runtime mode for future sessions.

func (*Manager) SetName added in v0.11.6

func (m *Manager) SetName(name string)

SetName sets the display name for this server instance (used in diagnostic reports).

func (*Manager) SetObfuscation

func (m *Manager) SetObfuscation(cfg obfuscation.Config)

SetObfuscation applies a new obfuscation config to all future sessions.

func (*Manager) SetRequireKnownPolicy added in v1.0.0

func (m *Manager) SetRequireKnownPolicy(enabled bool)

SetRequireKnownPolicy enables fail-closed auth for incoming sessions. When true, every connecting UUID must exist in active user policies.

func (*Manager) SetUserPolicies added in v0.2.0

func (m *Manager) SetUserPolicies(policies map[[16]byte]UserPolicy)

SetUserPolicies atomically replaces user policies.

type Session

type Session struct {

	// Traffic monitoring (session-lifetime counters)
	TrafficSent atomic.Uint64
	TrafficRecv atomic.Uint64
	// contains filtered or unexported fields
}

Session is a fully authenticated HiVoid session over a single QUIC connection.

func New

func New(conn *quic.Conn, cfg Config) (*Session, error)

New creates a Session that wraps an already-established QUIC connection. The hybrid key exchange (ClientHello/ServerHello) must be performed via PerformHandshake before this session is usable.

func (*Session) AcceptTunnel

func (s *Session) AcceptTunnel(ctx context.Context) (*quic.Stream, *frames.ProxyRequest, error)

AcceptTunnel accepts the next inbound proxy tunnel stream and reads its ProxyRequest.

func (*Session) ApplyRuntime added in v0.2.0

func (s *Session) ApplyRuntime(mode intelligence.Mode, obfsCfg obfuscation.Config)

func (*Session) ClientRequestedPolicy added in v0.6.0

func (s *Session) ClientRequestedPolicy() (uint8, uint8)

func (*Session) ClientUUID

func (s *Session) ClientUUID() [16]byte

func (*Session) Close

func (s *Session) Close() error

func (*Session) CloseWithError added in v0.7.0

func (s *Session) CloseWithError(code uint64, msg string) error

func (*Session) Connection

func (s *Session) Connection() *quic.Conn

Connection returns the underlying QUIC connection.

func (*Session) DecryptForTunnel

func (s *Session) DecryptForTunnel(nonce, ciphertext []byte) ([]byte, error)

func (*Session) DialTunnel

func (s *Session) DialTunnel(ctx context.Context, target string) (net.Conn, error)

DialTunnel opens a new multiplexed proxy tunnel (TCP) to the target address.

func (*Session) DialUDPTunnel added in v0.8.0

func (s *Session) DialUDPTunnel(ctx context.Context, target string) (net.Conn, error)

DialUDPTunnel opens a new multiplexed proxy tunnel (UDP) to the target address.

func (*Session) EncryptForTunnel

func (s *Session) EncryptForTunnel(plaintext []byte) (nonce, ciphertext []byte, err error)

func (*Session) GetTrafficStats added in v0.5.0

func (s *Session) GetTrafficStats() (uint64, uint64)

GetTrafficStats returns the total bytes sent and received during this session.

func (*Session) HandleRekeyFrame

func (s *Session) HandleRekeyFrame(f *frames.Frame) error

HandleRekeyFrame processes an inbound REKEY frame from the peer. It derives the same new keys using the provided salt and installs them.

CRITICAL: The receiver must use its DecryptKey as the base material, because that corresponds to the sender's EncryptKey (they are swapped between client and server). This ensures both sides derive from the exact same key material.

func (*Session) ID

func (s *Session) ID() ID

ID returns the session identifier.

func (*Session) PerformHandshakeAsClient

func (s *Session) PerformHandshakeAsClient(ctx context.Context) error

PerformHandshakeAsClient executes the client-side hybrid key exchange.

func (*Session) PerformHandshakeAsServer

func (s *Session) PerformHandshakeAsServer(ctx context.Context) error

PerformHandshakeAsServer executes the server-side hybrid key exchange.

func (*Session) RecvFrame

func (s *Session) RecvFrame() (*frames.Frame, error)

func (*Session) RecvStream

func (s *Session) RecvStream(ctx context.Context) ([]byte, error)

RecvStream accepts the next inbound QUIC data stream and returns its decrypted payload.

func (*Session) Salt

func (s *Session) Salt() []byte

func (*Session) SendFrame

func (s *Session) SendFrame(f *frames.Frame) error

func (*Session) SendStream

func (s *Session) SendStream(ctx context.Context, data []byte) error

SendStream opens a new QUIC data stream and writes encrypted payload to it.

func (*Session) StartControlLoop

func (s *Session) StartControlLoop()

StartControlLoop starts a background reader for control-stream frames. This is required so incoming REKEY frames are actually applied.

func (*Session) StartRekeyScheduler

func (s *Session) StartRekeyScheduler()

StartRekeyScheduler starts a background goroutine that triggers rekey on a timer. Only the CLIENT side actively triggers rekey events. The server side only responds to incoming REKEY frames via the control loop. This prevents race conditions where both sides try to rekey simultaneously.

func (*Session) StartTime added in v0.11.3

func (s *Session) StartTime() time.Time

StartTime returns when the session was created.

func (*Session) State

func (s *Session) State() State

State returns the current session state.

func (*Session) TriggerRekey

func (s *Session) TriggerRekey() error

TriggerRekey initiates a key rotation on this session. It sends a REKEY frame with a new salt to the peer, derives new keys, and installs them. Only the initiating side calls this.

This is safe to call from a goroutine; it serialises on the encryptMu.

func (*Session) WrapTunnel

func (s *Session) WrapTunnel(stream *quic.Stream, target string) net.Conn

WrapTunnel wraps a pre-negotiated QUIC stream into a net.Conn with AEAD encryption.

type SessionSnapshot added in v0.11.3

type SessionSnapshot struct {
	ConfigName string    `json:"config_name"`
	ID         string    `json:"id"`
	UUID       string    `json:"uuid"`
	Email      string    `json:"email"`
	RemoteAddr string    `json:"remote_addr"`
	StartTime  time.Time `json:"start_time"`
	Duration   string    `json:"duration"`
	TrafficIn  uint64    `json:"traffic_in"`
	TrafficOut uint64    `json:"traffic_out"`
	ConnCount  int       `json:"conn_count"`
}

SessionSnapshot contains diagnostic info for an active session.

type State

type State uint8

State tracks the session lifecycle state.

const (
	StateHandshaking State = iota
	StateActive
	StateRekeying
	StateClosed
)

func (State) String

func (s State) String() string

type TunnelConn

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

TunnelConn wraps a QUIC bidirectional stream, exposing a net.Conn interface with application-layer AEAD encryption/decryption.

func (*TunnelConn) Close

func (c *TunnelConn) Close() error

Close fully shuts down the tunnel stream.

func (*TunnelConn) CloseWrite

func (c *TunnelConn) CloseWrite() error

CloseWrite closes only the write side of the tunnel (sends QUIC FIN). The read side remains open so the peer can finish sending.

func (*TunnelConn) LocalAddr

func (c *TunnelConn) LocalAddr() net.Addr

LocalAddr returns a placeholder local address.

func (*TunnelConn) RawStream

func (c *TunnelConn) RawStream() *quic.Stream

RawStream returns the underlying QUIC stream for low-level access by the forwarder.

func (*TunnelConn) Read

func (c *TunnelConn) Read(b []byte) (int, error)

Read decrypts the next frame from the tunnel stream and returns the plaintext. Partial reads are supported: leftover bytes are buffered and returned on the next call.

func (*TunnelConn) RemoteAddr

func (c *TunnelConn) RemoteAddr() net.Addr

RemoteAddr returns the target address of this tunnel.

func (*TunnelConn) SetDeadline

func (c *TunnelConn) SetDeadline(t time.Time) error

SetDeadline sets both read and write deadlines.

func (*TunnelConn) SetReadDeadline

func (c *TunnelConn) SetReadDeadline(t time.Time) error

SetReadDeadline sets the read deadline.

func (*TunnelConn) SetWriteDeadline

func (c *TunnelConn) SetWriteDeadline(t time.Time) error

SetWriteDeadline sets the write deadline.

func (*TunnelConn) Write

func (c *TunnelConn) Write(b []byte) (int, error)

Write encrypts plaintext and writes it as one or more FrameData frames. Large writes are chunked to tunnelReadBufSize bytes per frame. Uses a pooled buffer and writes each frame fully even if the stream performs short writes under backpressure.

type UserPolicy added in v0.2.0

type UserPolicy struct {
	UUID           [16]byte
	Email          string
	CertPin        string
	Mode           intelligence.Mode
	ObfsConfig     obfuscation.Config
	MaxConnections int
	MaxIPs         int
	BindIP         string
	BandwidthLimit int64
	DataLimit      int64
	ExpireAtUnix   int64
	BytesIn        uint64
	BytesOut       uint64
	Enabled        bool
	BlockedHosts   []string
	BlockedTags    []string
	DirectGeoSite  []string
	DirectGeoIP    []string
	DirectDomains  []string
	DirectIPs      []string
}

UserPolicy defines runtime settings for a specific user UUID.

Jump to

Keyboard shortcuts

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