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
- Variables
- func ObfsConfigForName(name string) obfuscation.Config
- func ObfsConfigToName(cfg obfuscation.Config) string
- func ObfsNameToID(name string) uint8
- func SendProxyErrToStream(stream *quic.Stream, msg string)
- func SendProxyError(stream *quic.Stream, msg string) error
- func SendProxyOK(stream *quic.Stream) error
- func SendProxyOkToStream(stream *quic.Stream) error
- type Config
- type ID
- type Manager
- func (m *Manager) AcceptAndHandshake(ctx context.Context, conn *quic.Conn) (*Session, error)
- func (m *Manager) CloseAll()
- func (m *Manager) Count() int
- func (m *Manager) Dial(ctx context.Context, conn *quic.Conn) (*Session, error)
- func (m *Manager) EnforceQuotas()
- func (m *Manager) Get(id ID) (*Session, bool)
- func (m *Manager) GetActiveSnapshots() []SessionSnapshot
- func (m *Manager) GetPoliciesSnapshot() map[[16]byte]UserPolicy
- func (m *Manager) GetPolicy(uuid [16]byte) (UserPolicy, bool)
- func (m *Manager) KickAll()
- func (m *Manager) KickUser(uuid [16]byte)
- func (m *Manager) Name() string
- func (m *Manager) RefreshActiveSessionPolicies()
- func (m *Manager) Remove(id ID)
- func (m *Manager) SetAllowedUUIDs(uuids [][16]byte)
- func (m *Manager) SetClientParams(mode intelligence.Mode, obfsName string)
- func (m *Manager) SetClientUUID(u [16]byte)
- func (m *Manager) SetMode(mode intelligence.Mode)
- func (m *Manager) SetName(name string)
- func (m *Manager) SetObfuscation(cfg obfuscation.Config)
- func (m *Manager) SetRequireKnownPolicy(enabled bool)
- func (m *Manager) SetUserPolicies(policies map[[16]byte]UserPolicy)
- type Session
- func (s *Session) AcceptTunnel(ctx context.Context) (*quic.Stream, *frames.ProxyRequest, error)
- func (s *Session) ApplyRuntime(mode intelligence.Mode, obfsCfg obfuscation.Config)
- func (s *Session) ClientRequestedPolicy() (uint8, uint8)
- func (s *Session) ClientUUID() [16]byte
- func (s *Session) Close() error
- func (s *Session) CloseWithError(code uint64, msg string) error
- func (s *Session) Connection() *quic.Conn
- func (s *Session) DecryptForTunnel(nonce, ciphertext []byte) ([]byte, error)
- func (s *Session) DialTunnel(ctx context.Context, target string) (net.Conn, error)
- func (s *Session) DialUDPTunnel(ctx context.Context, target string) (net.Conn, error)
- func (s *Session) EncryptForTunnel(plaintext []byte) (nonce, ciphertext []byte, err error)
- func (s *Session) GetTrafficStats() (uint64, uint64)
- func (s *Session) HandleRekeyFrame(f *frames.Frame) error
- func (s *Session) ID() ID
- func (s *Session) PerformHandshakeAsClient(ctx context.Context) error
- func (s *Session) PerformHandshakeAsServer(ctx context.Context) error
- func (s *Session) RecvFrame() (*frames.Frame, error)
- func (s *Session) RecvStream(ctx context.Context) ([]byte, error)
- func (s *Session) Salt() []byte
- func (s *Session) SendFrame(f *frames.Frame) error
- func (s *Session) SendStream(ctx context.Context, data []byte) error
- func (s *Session) StartControlLoop()
- func (s *Session) StartRekeyScheduler()
- func (s *Session) StartTime() time.Time
- func (s *Session) State() State
- func (s *Session) TriggerRekey() error
- func (s *Session) WrapTunnel(stream *quic.Stream, target string) net.Conn
- type SessionSnapshot
- type State
- type TunnelConn
- func (c *TunnelConn) Close() error
- func (c *TunnelConn) CloseWrite() error
- func (c *TunnelConn) LocalAddr() net.Addr
- func (c *TunnelConn) RawStream() *quic.Stream
- func (c *TunnelConn) Read(b []byte) (int, error)
- func (c *TunnelConn) RemoteAddr() net.Addr
- func (c *TunnelConn) SetDeadline(t time.Time) error
- func (c *TunnelConn) SetReadDeadline(t time.Time) error
- func (c *TunnelConn) SetWriteDeadline(t time.Time) error
- func (c *TunnelConn) Write(b []byte) (int, error)
- type UserPolicy
Constants ¶
const ( // GhostDefaultFrameSize is the MTU-optimized payload size for all frames. GhostDefaultFrameSize = 1024 // GhostMaxQueueSize bounds memory usage under congestion. GhostMaxQueueSize = 2048 )
Variables ¶
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
ObfsNameToID converts an obfuscation config string to its wire ID for ClientHello.
func SendProxyErrToStream ¶
SendProxyErrToStream writes a failure ProxyResponse to the stream.
func SendProxyError ¶ added in v0.7.0
SendProxyError writes a failure proxy response to the stream.
func SendProxyOK ¶
SendProxyOK writes a successful proxy response to the stream.
func SendProxyOkToStream ¶
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 ¶
DefaultConfig returns production-ready session defaults.
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager manages a pool of active HiVoid sessions.
func NewManager ¶
NewManager creates a Manager.
func (*Manager) AcceptAndHandshake ¶
AcceptAndHandshake wraps a newly accepted QUIC connection into a Session, performs the server-side handshake, and registers it.
func (*Manager) EnforceQuotas ¶ added in v0.7.0
func (m *Manager) EnforceQuotas()
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
KickUser forcefully closes all active sessions for a specific UUID. Uses custom error code 0x10 to signify policy/limit reached.
func (*Manager) RefreshActiveSessionPolicies ¶ added in v0.2.0
func (m *Manager) RefreshActiveSessionPolicies()
RefreshActiveSessionPolicies reapplies user policy mode/obfs to active sessions.
func (*Manager) SetAllowedUUIDs ¶
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 ¶
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
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
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 ¶
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 ¶
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 (*Session) ClientUUID ¶
func (*Session) CloseWithError ¶ added in v0.7.0
func (*Session) Connection ¶
Connection returns the underlying QUIC connection.
func (*Session) DecryptForTunnel ¶
func (*Session) DialTunnel ¶
DialTunnel opens a new multiplexed proxy tunnel (TCP) to the target address.
func (*Session) DialUDPTunnel ¶ added in v0.8.0
DialUDPTunnel opens a new multiplexed proxy tunnel (UDP) to the target address.
func (*Session) EncryptForTunnel ¶
func (*Session) GetTrafficStats ¶ added in v0.5.0
GetTrafficStats returns the total bytes sent and received during this session.
func (*Session) HandleRekeyFrame ¶
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) PerformHandshakeAsClient ¶
PerformHandshakeAsClient executes the client-side hybrid key exchange.
func (*Session) PerformHandshakeAsServer ¶
PerformHandshakeAsServer executes the server-side hybrid key exchange.
func (*Session) RecvStream ¶
RecvStream accepts the next inbound QUIC data stream and returns its decrypted payload.
func (*Session) SendStream ¶
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) TriggerRekey ¶
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.
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 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.