core

package
v0.0.0-...-d49e497 Latest Latest
Warning

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

Go to latest
Published: May 25, 2026 License: MIT Imports: 36 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrStopLogWalk = errors.New("stop log walk")

ErrStopLogWalk is returned by a WalkHot visitor to stop iteration early.

View Source
var ErrUserAssignedToAnotherInbound = errors.New("user is already assigned to another inbound")
View Source
var Stats = &SystemStats{
	History: make([]TrafficPoint, 0),
}

Functions

func AuditDBPathFor

func AuditDBPathFor(mainDBPath string) string

AuditDBPathFor derives the audit DB path from the main DB path. e.g. "data/stats.db" → "data/audit.db"

func BackupDBToTarGz

func BackupDBToTarGz(ctx context.Context, db *sql.DB, archiveName, destPath string) error

BackupDBToTarGz takes a snapshot of db via VACUUM INTO, then wraps the snapshot file in a tar.gz archive written to destPath. archiveName is the filename stored inside the tar (e.g. "stats.db").

func BackupDBWithColdToTarGz

func BackupDBWithColdToTarGz(ctx context.Context, db *sql.DB, archiveName, destPath string, coldFiles []string) error

BackupDBWithColdToTarGz is like BackupDBToTarGz but also appends cold segment files (already-compressed .log.gz) into the same tar archive. coldFiles is a list of absolute paths; each is stored in the tar under "cold/<basename>".

func CanonicalRouteTagRuleMatch

func CanonicalRouteTagRuleMatch(rule map[string]interface{}) (string, error)

func CensorLine

func CensorLine(line string) string

CensorLine returns the log line with source IP and destination host:port replaced by "***". Lines that do not match the sing-box accepted/rejected connection-log format are returned unchanged.

func DetectPublicIP

func DetectPublicIP() string

DetectPublicIP attempts to detect the public IP address It priorities: 1. OGS_PUBLIC_IP environment variable 2. External IP detection services (HTTP) 3. Local interface inspection (fallback)

func GenerateWireGuardKeys

func GenerateWireGuardKeys() (string, string, error)

func GetWireGuardStats

func GetWireGuardStats() (map[string]PeerStats, error)

func LogDBPathFor

func LogDBPathFor(mainDBPath string) string

LogDBPathFor derives the log DB path from the main DB path. e.g. "data/stats.db" → "data/singbox_logs.db"

func QuotaWindowStart

func QuotaWindowStart(period string, now time.Time) int64

QuotaWindowStart returns the Unix timestamp of the start of the current quota window for the given period string. It is exported so API handlers can use the same window boundary logic when computing display usage.

func SanitiseManagedInboundFields

func SanitiseManagedInboundFields(inbound map[string]interface{})

SanitiseManagedInboundFields removes protocol/transport-specific fields that must not survive a managed inbound write.

func SubscriptionUsageWindowStart

func SubscriptionUsageWindowStart(period string, now time.Time) int64

SubscriptionUsageWindowStart returns the Unix timestamp of the start of the current quota window for a subscription's period string. Exported for use in API display handlers.

Types

type AnyTLSInbound

type AnyTLSInbound struct {
	InboundBase
	ListenFields
	Users         []AnyTLSUser    `json:"users"`
	PaddingScheme []string        `json:"padding_scheme,omitempty"`
	TLS           json.RawMessage `json:"tls,omitempty"`
}

func (*AnyTLSInbound) Base

func (a *AnyTLSInbound) Base() InboundBase

func (*AnyTLSInbound) UserNames

func (a *AnyTLSInbound) UserNames() []string

type AnyTLSUser

type AnyTLSUser struct {
	Name     string `json:"name"`
	Password string `json:"password"`
}

type AuditEntry

type AuditEntry struct {
	ID       int64  `json:"id"`
	Ts       int64  `json:"ts"`
	Actor    string `json:"actor"`
	IP       string `json:"ip"`
	Action   string `json:"action"`
	Domain   string `json:"domain"`
	EntityID string `json:"entity_id"`
	Detail   string `json:"detail"`
}

AuditEntry is one row in the audit_log table.

type AuditLogPage

type AuditLogPage struct {
	Items      []AuditEntry `json:"items"`
	NextOffset int          `json:"next_offset"`
	HasMore    bool         `json:"has_more"`
}

AuditLogPage is the paginated response for GET /api/audit-log.

type AuditStore

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

AuditStore is a separate SQLite DB holding only the audit_log table.

func NewAuditStore

func NewAuditStore(dbPath string) (*AuditStore, error)

func (*AuditStore) Close

func (a *AuditStore) Close()

func (*AuditStore) DB

func (a *AuditStore) DB() *sql.DB

DB returns the underlying *sql.DB (used by the backup system).

func (*AuditStore) InsertAuditLog

func (a *AuditStore) InsertAuditLog(ctx context.Context, e AuditEntry) error

InsertAuditLog writes a single audit entry. Errors are swallowed by the caller — audit failures must never break the primary operation.

func (*AuditStore) PruneToSize

func (a *AuditStore) PruneToSize(maxBytes int64)

PruneToSize deletes the oldest rows in batches until the file is at or below maxBytes, then runs PRAGMA incremental_vacuum to reclaim space. Batch size is 500 rows; stops after 50 iterations to bound runtime.

func (*AuditStore) QueryAuditLog

func (a *AuditStore) QueryAuditLog(ctx context.Context, limit, offset int, domain, action string) (AuditLogPage, error)

QueryAuditLog returns paginated audit entries ordered by ts DESC. domain and action are optional filters ("" = no filter).

func (*AuditStore) SizeBytes

func (a *AuditStore) SizeBytes() int64

SizeBytes returns the current on-disk size of the audit DB file.

type Calculator

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

func NewCalculator

func NewCalculator(w activeUserSource, sb *SingboxClient, s *Store, inboundTags []string) *Calculator

func (*Calculator) Start

func (c *Calculator) Start()

type ClashAPI

type ClashAPI struct {
	ExternalController string                     `json:"external_controller,omitempty"`
	Secret             string                     `json:"secret,omitempty"`
	Extra              map[string]json.RawMessage `json:"-"`
	// contains filtered or unexported fields
}

func (ClashAPI) MarshalJSON

func (c ClashAPI) MarshalJSON() ([]byte, error)

func (*ClashAPI) UnmarshalJSON

func (c *ClashAPI) UnmarshalJSON(data []byte) error

type Config

type Config struct {
	SingboxConfigPath     string   `json:"singbox_config_path" env:"OGS_SINGBOX_CONFIG_PATH" env-default:"/etc/sing-box/config.json"`
	SingboxAPIAddr        string   `json:"singbox_api_addr" env:"OGS_SINGBOX_API_ADDR" env-default:"127.0.0.1:8080"`
	ManagedInbounds       []string `json:"managed_inbounds" env:"OGS_MANAGED_INBOUNDS" env-default:"in-reality"`
	StatsInbounds         []string `json:"stats_inbounds" env:"OGS_STATS_INBOUNDS" env-default:"in-reality"`
	StatsOutbounds        []string `json:"stats_outbounds" env:"OGS_STATS_OUTBOUNDS" env-default:"direct"`
	AccessLogPath         string   `json:"access_log_path" env:"OGS_ACCESS_LOG_PATH" env-default:"data/access.log"`
	DatabasePath          string   `json:"database_path" env:"OGS_DB_PATH" env-default:"data/stats.db"`
	ListenAddr            string   `json:"listen_addr" env:"OGS_LISTEN_ADDR" env-default:":8080"`
	WireGuardConfigPath   string   `json:"wireguard_config_path" env:"OGS_WIREGUARD_CONFIG_PATH" env-default:"/etc/wireguard/wg0.conf"`
	WireGuardConfigDir    string   `json:"wireguard_config_dir" env:"OGS_WIREGUARD_CONFIG_DIR"`
	EnableWireGuard       bool     `json:"enable_wireguard" env:"OGS_ENABLE_WIREGUARD" env-default:"true"`
	EnableSingbox         bool     `json:"enable_singbox" env:"OGS_ENABLE_SINGBOX" env-default:"true"`
	UseStatsSampler       bool     `json:"use_stats_sampler" env:"OGS_USE_STATS_SAMPLER" env-default:"true"`
	SamplerIntervalSec    int      `json:"sampler_interval_sec" env:"OGS_SAMPLER_INTERVAL_SEC" env-default:"120"`
	ActiveThresholdBytes  int64    `json:"active_threshold_bytes" env:"OGS_ACTIVE_THRESHOLD_BYTES" env-default:"1024"`
	RetentionEnabled      bool     `json:"retention_enabled" env:"OGS_RETENTION_ENABLED" env-default:"false"`
	RetentionDays         int      `json:"retention_days" env:"OGS_RETENTION_DAYS" env-default:"90"`
	WGSamplerIntervalSec  int      `json:"wg_sampler_interval_sec" env:"OGS_WG_SAMPLER_INTERVAL_SEC" env-default:"60"`
	WGRetentionDays       int      `json:"wg_retention_days" env:"OGS_WG_RETENTION_DAYS" env-default:"30"`
	AggregationEnabled    bool     `json:"aggregation_enabled" env:"OGS_AGGREGATION_ENABLED" env-default:"false"`
	AggregationDays       int      `json:"aggregation_days" env:"OGS_AGGREGATION_DAYS" env-default:"7"`
	AuditLogMaxMB         int      `json:"audit_log_max_mb" env:"OGS_AUDIT_LOG_MAX_MB" env-default:"50"`
	LogRetentionMode      string   `json:"log_retention_mode" env:"OGS_LOG_RETENTION_MODE" env-default:"size"` // "size" or "time"
	LogRetentionMB        int      `json:"log_retention_mb" env:"OGS_LOG_RETENTION_MB" env-default:"200"`
	LogRetentionDays      int      `json:"log_retention_days" env:"OGS_LOG_RETENTION_DAYS" env-default:"30"`
	LogRetentionUnit      string   `json:"log_retention_unit" env:"OGS_LOG_RETENTION_UNIT" env-default:"days"` // "days"|"weeks"|"months"
	LogColdDir            string   `json:"log_cold_dir" env:"OGS_LOG_COLD_DIR" env-default:"data/logs"`
	DBBackupPath          string   `json:"db_backup_path" env:"OGS_DB_BACKUP_PATH" env-default:"data/backups"`
	DBBackupIntervalHours int      `json:"db_backup_interval_hours" env:"OGS_DB_BACKUP_INTERVAL_HOURS" env-default:"24"`
	PublicIP              string   `json:"public_ip" env:"OGS_PUBLIC_IP"`
	SubscriptionDomain    string   `json:"subscription_domain" env:"OGS_SUBSCRIPTION_DOMAIN"`
	CFWorkerURL           string   `json:"cf_worker_url" env:"OGS_CF_WORKER_URL"`
	SingboxPendingChanges bool     `json:"-"` // Not persisted, runtime flag
	ConfigPath            string   `json:"-"`
	APIKey                string   `json:"api_key" env:"OGS_API_KEY"`
	APIKeyReadOnly        bool     `json:"api_key_read_only" env:"OGS_API_KEY_READ_ONLY" env-default:"false"`
	DemoMode              bool     `json:"demo_mode" env:"OGS_DEMO_MODE" env-default:"false"`
	DisablePasswordLogin  bool     `json:"disable_password_login" env:"OGS_DISABLE_PASSWORD_LOGIN" env-default:"false"`

	// Execution mode: "local" (default/bare metal), "docker_local" (Docker on same host).
	ExecutionMode string `json:"execution_mode" env:"OGS_EXECUTION_MODE"`

	// WireGuard test mode: when true, WireGuard service/wg calls are simulated so UI flows can be tested without wg/systemd installed.
	WireGuardTestMode bool `json:"wireguard_test_mode" env:"OGS_WIREGUARD_TEST_MODE" env-default:"false"`

	// Sysctl Whitelist (Optional override)
	SysctlWhitelist []string `json:"sysctl_whitelist" env:"OGS_SYSCTL_WHITELIST"`

	JWTSecret string `json:"jwt_secret" env:"OGS_JWT_SECRET"`

	SubscriptionProtection SubscriptionProtectionConfig `json:"subscription_protection"`
	// contains filtered or unexported fields
}

func LoadConfig

func LoadConfig(path ...string) *Config

func (*Config) AddSingboxInbound

func (c *Config) AddSingboxInbound(newInbound map[string]interface{}) error

AddSingboxInbound appends a new inbound block

func (*Config) AddUser

func (c *Config) AddUser(name, uuid, flow, inboundTag, vmessSecurity string, vmessAlterID int) error

func (*Config) ApplySingboxChanges

func (c *Config) ApplySingboxChanges() error

ApplySingboxChanges applies pending Sing-box configuration changes. Attempts restart via Clash API POST /restart first; falls back to signaling the caller that a systemctl restart is required.

func (*Config) ApplyWireGuardTestModeDefaults

func (c *Config) ApplyWireGuardTestModeDefaults()

ApplyWireGuardTestModeDefaults keeps WireGuard test-mode artifacts inside the project/config directory. It prevents accidental writes under system paths such as /etc/wireguard.

func (*Config) ClearSingboxPendingChanges

func (c *Config) ClearSingboxPendingChanges()

func (*Config) DeleteSingboxInbound

func (c *Config) DeleteSingboxInbound(tag string) error

DeleteSingboxInbound removes an inbound by tag

func (*Config) DetectPortCollision

func (c *Config) DetectPortCollision(content []byte) error

DetectPortCollision parses the config and checks for overlapping ports in inbounds

func (*Config) GetActiveUsers

func (c *Config) GetActiveUsers() ([]UserAccount, error)

func (*Config) GetSingboxConfig

func (c *Config) GetSingboxConfig() (string, error)

GetSingboxConfig reads the raw config file content

func (*Config) GetSingboxConfigMap

func (c *Config) GetSingboxConfigMap() (map[string]interface{}, error)

GetSingboxConfigMap reads the raw config file content as a map

func (*Config) GetSingboxDNS

func (c *Config) GetSingboxDNS() (map[string]interface{}, error)

func (*Config) GetSingboxInboundByTag

func (c *Config) GetSingboxInboundByTag(tag string) (map[string]interface{}, error)

func (*Config) GetSingboxInboundMeta

func (c *Config) GetSingboxInboundMeta(tag string) (*SingboxInboundMeta, error)

func (*Config) GetSingboxInboundMetas

func (c *Config) GetSingboxInboundMetas() ([]SingboxInboundMeta, error)

func (*Config) GetSingboxInboundView

func (c *Config) GetSingboxInboundView(tag string) (*SingboxInboundView, error)

func (*Config) GetSingboxInboundViews

func (c *Config) GetSingboxInboundViews() ([]SingboxInboundView, error)

func (*Config) GetSingboxInbounds

func (c *Config) GetSingboxInbounds() ([]map[string]interface{}, error)

GetSingboxInbounds returns the list of inbounds as map objects.

func (*Config) GetSingboxOutboundViews

func (c *Config) GetSingboxOutboundViews() ([]SingboxOutboundView, error)

func (*Config) GetSingboxPendingChanges

func (c *Config) GetSingboxPendingChanges() bool

func (*Config) GetSingboxRouteRules

func (c *Config) GetSingboxRouteRules() ([]map[string]interface{}, error)

GetSingboxRouteRules reads the current route.rules array from the config.

func (*Config) GetUserInbounds

func (c *Config) GetUserInbounds(name string) ([]UserInboundInfo, error)

GetUserInbounds returns inbound tags with per-inbound flow/uuid for a user.

func (*Config) MarkSingboxPending

func (c *Config) MarkSingboxPending()

MarkSingboxPending marks that Sing-box configuration has pending changes

func (*Config) ModifySingboxConfig

func (c *Config) ModifySingboxConfig(modifier func(*SingboxConfig) error) error

ModifySingboxConfig safely modifies the configuration using a callback

func (*Config) ReloadSingbox

func (c *Config) ReloadSingbox() error

func (*Config) RemoveInboundFromLists

func (c *Config) RemoveInboundFromLists(tag string) error

RemoveInboundFromLists removes an inbound tag from managed_inbounds and stats_inbounds

func (*Config) RemoveUser

func (c *Config) RemoveUser(name string) error

func (*Config) RemoveUserFromInbound

func (c *Config) RemoveUserFromInbound(name, inboundTag string) error

func (*Config) RenameInboundInLists

func (c *Config) RenameInboundInLists(oldTag, newTag string) error

RenameInboundInLists updates an inbound tag in managed_inbounds and stats_inbounds

func (*Config) RenameUser

func (c *Config) RenameUser(originalName, newName, uuid, flow, vmessSecurity string, vmessAlterID int) error

func (*Config) ReplaceSingboxRouteRules

func (c *Config) ReplaceSingboxRouteRules(rules []map[string]interface{}) error

func (*Config) ResolveRouteTagRule

func (c *Config) ResolveRouteTagRule(ruleMatchJSON string) (RouteTagRuleResolution, error)

func (*Config) ResolveUserRouteTags

func (c *Config) ResolveUserRouteTags(userName string, tags []UserRouteTag) ([]UserRouteTag, error)

func (*Config) SaveAppConfig

func (c *Config) SaveAppConfig() error

func (*Config) SetExecutor

func (c *Config) SetExecutor(exec SystemExecutor)

func (*Config) SyncInboundsFromSingbox

func (c *Config) SyncInboundsFromSingbox() error

func (*Config) UpdateSingboxConfig

func (c *Config) UpdateSingboxConfig(content string) error

UpdateSingboxConfig writes raw content to config file and restarts service

func (*Config) UpdateSingboxDNS

func (c *Config) UpdateSingboxDNS(dns map[string]interface{}) error

func (*Config) UpdateSingboxInbound

func (c *Config) UpdateSingboxInbound(tag string, updatedInbound map[string]interface{}) error

UpdateSingboxInbound updates an existing inbound by tag

func (*Config) UpdateSingboxOutboundDomainStrategies

func (c *Config) UpdateSingboxOutboundDomainStrategies(updates []SingboxOutboundDomainStrategyUpdate) error

func (*Config) UpdateUser

func (c *Config) UpdateUser(name, uuid, flow, inboundTag, vmessSecurity string, vmessAlterID int) error

func (*Config) UpdateUserInInbound

func (c *Config) UpdateUserInInbound(name, uuid, flow, inboundTag, vmessSecurity string, vmessAlterID int) error

func (*Config) UpdateUserRouteTagMembership

func (c *Config) UpdateUserRouteTagMembership(userName string, targetTagIDs []int64, tags []UserRouteTag) ([]UserRouteTag, error)

func (*Config) UpsertSingboxRouteRules

func (c *Config) UpsertSingboxRouteRules(newRules []map[string]interface{}) error

UpsertSingboxRouteRules merges newRules into route.rules, skipping duplicates. Two rules are considered identical when their inbound+protocol+action+outbound fields match.

func (*Config) ValidateConfig

func (c *Config) ValidateConfig(content []byte) error

type DailyUsage

type DailyUsage struct {
	User      string
	Timestamp int64 // Bucket start timestamp
	Uplink    int64
	Downlink  int64
}

DailyUsage represents aggregated traffic data for a user on a specific bucket (8h).

type DashboardPreferences

type DashboardPreferences struct {
	DefaultService          string `json:"default_service"`
	RefreshMs               int    `json:"refresh_ms"`
	DefaultRange            string `json:"default_range"`
	ActiveUserWindowMinutes int    `json:"active_user_window_minutes"`
	DetailChartTargetPoints int    `json:"detail_chart_target_points"`
}

func DefaultDashboardPreferences

func DefaultDashboardPreferences() DashboardPreferences

type Experimental

type Experimental struct {
	V2RayAPI  *V2RayAPI                  `json:"v2ray_api,omitempty"`
	ClashAPI  *ClashAPI                  `json:"clash_api,omitempty"`
	CacheFile json.RawMessage            `json:"cache_file,omitempty"`
	Extra     map[string]json.RawMessage `json:"-"`
}

func (Experimental) MarshalJSON

func (e Experimental) MarshalJSON() ([]byte, error)

func (*Experimental) UnmarshalJSON

func (e *Experimental) UnmarshalJSON(data []byte) error

type Hysteria2Inbound

type Hysteria2Inbound struct {
	InboundBase
	ListenFields
	UpMbps                int             `json:"up_mbps,omitempty"`
	DownMbps              int             `json:"down_mbps,omitempty"`
	Obfs                  *Hysteria2Obfs  `json:"obfs,omitempty"`
	Users                 []Hysteria2User `json:"users"`
	IgnoreClientBandwidth bool            `json:"ignore_client_bandwidth,omitempty"`
	TLS                   json.RawMessage `json:"tls,omitempty"`
	Masquerade            json.RawMessage `json:"masquerade,omitempty"`
	BBRProfile            string          `json:"bbr_profile,omitempty"`
}

func (*Hysteria2Inbound) Base

func (h *Hysteria2Inbound) Base() InboundBase

func (*Hysteria2Inbound) UserNames

func (h *Hysteria2Inbound) UserNames() []string

type Hysteria2Obfs

type Hysteria2Obfs struct {
	Type     string `json:"type"` // always "salamander" — no omitempty, must be present when block exists
	Password string `json:"password"`
}

type Hysteria2User

type Hysteria2User struct {
	Name     string `json:"name"`
	Password string `json:"password"`
}

type InboundBase

type InboundBase struct {
	Type string `json:"type"`
	Tag  string `json:"tag"`
}

type InboundMeta

type InboundMeta struct {
	Tag               string `json:"tag"`
	ExternalPort      int    `json:"external_port"`
	ClientSNI         string `json:"client_sni,omitempty"`
	LinkAllowInsecure *bool  `json:"link_allow_insecure,omitempty"`
	OverrideAddress   string `json:"override_address,omitempty"`
}

type ListenFields

type ListenFields struct {
	Listen               string          `json:"listen,omitempty"`
	ListenPort           int             `json:"listen_port,omitempty"`
	BindInterface        string          `json:"bind_interface,omitempty"`
	RoutingMark          json.RawMessage `json:"routing_mark,omitempty"` // int | "0xHEX" union type
	ReuseAddr            bool            `json:"reuse_addr,omitempty"`
	Netns                string          `json:"netns,omitempty"`
	TCPFastOpen          bool            `json:"tcp_fast_open,omitempty"`
	TCPMultiPath         bool            `json:"tcp_multi_path,omitempty"`
	DisableTCPKeepAlive  bool            `json:"disable_tcp_keep_alive,omitempty"`
	TCPKeepAlive         string          `json:"tcp_keep_alive,omitempty"`
	TCPKeepAliveInterval string          `json:"tcp_keep_alive_interval,omitempty"`
	UDPFragment          bool            `json:"udp_fragment,omitempty"`
	UDPTimeout           string          `json:"udp_timeout,omitempty"`
	Detour               string          `json:"detour,omitempty"`
}

type LogIngester

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

LogIngester tails AccessLogPath every 1 second, inserts new lines into LogStore, and maintains an in-memory active-users map so Calculator keeps working without modification to its call sites.

func NewLogIngester

func NewLogIngester(logPath string, store *LogStore) *LogIngester

NewLogIngester creates a LogIngester. Call Start() to begin tailing.

func (*LogIngester) GetActiveUsers

func (i *LogIngester) GetActiveUsers(windowSeconds int64) []string

GetActiveUsers returns users who were seen in the log within the last windowSeconds seconds. Signature is identical to Watcher.GetActiveUsers so Calculator can accept either via the activeUserSource interface.

func (*LogIngester) Start

func (i *LogIngester) Start()

Start launches the poll loop and retention ticker in background goroutines.

func (*LogIngester) Stop

func (i *LogIngester) Stop()

Stop signals both background goroutines to exit.

type LogRow

type LogRow struct {
	ID    int64  `json:"id"`
	Ts    int64  `json:"ts"` // unix ms
	Raw   string `json:"raw"`
	Level string `json:"level"`
	User  string `json:"user"`
}

LogRow is one row in the singbox_logs table.

type LogSegment

type LogSegment struct {
	ID        int64  `json:"id"`
	Filename  string `json:"filename"`
	StartTs   int64  `json:"start_ts"`
	EndTs     int64  `json:"end_ts"`
	RowCount  int64  `json:"row_count"`
	SizeBytes int64  `json:"size_bytes"`
}

LogSegment is one row in the log_segments table.

type LogStore

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

LogStore owns the singbox_logs.db SQLite database.

func NewLogStore

func NewLogStore(dbPath string) (*LogStore, error)

NewLogStore opens (or creates) the log database at dbPath, applies pragmas, and initialises the schema.

func (*LogStore) CheckRetention

func (l *LogStore) CheckRetention(ctx context.Context, mode string, maxMB, days int, unit, coldDir string) (*LogSegment, error)

CheckRetention inspects the current hot tier and exports old rows if the configured threshold is exceeded.

mode "size": export oldest ~50% of rows when SizeBytes() > maxMB*1024*1024. mode "time": export rows with ts < now - duration(days, unit) where unit is

"days", "weeks", or "months".

Returns the created segment if anything was exported (nil, nil otherwise).

func (*LogStore) Close

func (l *LogStore) Close()

Close closes the database connection.

func (*LogStore) DB

func (l *LogStore) DB() *sql.DB

DB returns the underlying *sql.DB (used by the backup system in 49-06).

func (*LogStore) ExportToCold

func (l *LogStore) ExportToCold(ctx context.Context, coldDir string, maxID int64) (*LogSegment, error)

ExportToCold streams rows with id <= maxID into coldDir/singbox_YYYYMMDD-YYYYMMDD.log.gz, inserts a log_segments row, deletes the exported rows from singbox_logs and singbox_logs_fts in one transaction, then runs PRAGMA incremental_vacuum. Returns the created segment. Returns nil, nil if there are no rows to export.

func (*LogStore) HotDateRange

func (l *LogStore) HotDateRange(ctx context.Context) (firstMs, lastMs int64, err error)

HotDateRange returns MIN(ts) and MAX(ts) from singbox_logs. Both are 0 if the table is empty. Used by backup filename generation.

func (*LogStore) InsertLogs

func (l *LogStore) InsertLogs(ctx context.Context, ts int64, lines []string) error

InsertLogs inserts a batch of raw log lines in one transaction. ts is unix ms (caller supplies time.Now().UnixMilli()). Both singbox_logs and the FTS5 content table are kept in sync.

func (*LogStore) ListSegments

func (l *LogStore) ListSegments(ctx context.Context, limit int) ([]LogSegment, error)

ListSegments returns segments ordered by start_ts DESC (newest first). limit <= 0 returns all segments.

func (*LogStore) OldestHotTs

func (l *LogStore) OldestHotTs(ctx context.Context) (int64, error)

OldestHotTs returns the smallest ts currently in singbox_logs (0 if empty).

func (*LogStore) PollAfterID

func (l *LogStore) PollAfterID(ctx context.Context, afterID int64, limit int) ([]LogRow, error)

PollAfterID returns up to limit rows with id > afterID, ordered id ASC. Used for live-tail incremental polling.

func (*LogStore) RowCount

func (l *LogStore) RowCount(ctx context.Context) (int64, error)

RowCount returns the total number of rows in singbox_logs.

func (*LogStore) SegmentStats

func (l *LogStore) SegmentStats(ctx context.Context) (count int64, totalBytes int64, err error)

SegmentStats returns the count and total size_bytes of all rows in log_segments.

func (*LogStore) SegmentsInRange

func (l *LogStore) SegmentsInRange(ctx context.Context, fromMs, toMs int64) ([]LogSegment, error)

SegmentsInRange returns segments whose [start_ts, end_ts] overlaps [fromMs, toMs], ordered start_ts DESC. If both fromMs and toMs are <= 0, all segments are returned.

func (*LogStore) SizeBytes

func (l *LogStore) SizeBytes() int64

SizeBytes returns the current on-disk size of the log DB file.

func (*LogStore) TailHot

func (l *LogStore) TailHot(ctx context.Context, limit int) ([]LogRow, error)

TailHot returns the most recent limit rows in chronological order (oldest first).

func (*LogStore) WalkHot

func (l *LogStore) WalkHot(ctx context.Context, simpleText string, fromMs, toMs int64, visit func(LogRow) error) error

WalkHot streams rows matching the time range and optional simple text in newest-first order. If simpleText != "", uses FTS5 MATCH with the term double-quoted (double-quote chars inside the term are escaped as ""). If simpleText == "", scans singbox_logs with the ts filter only. visit may return ErrStopLogWalk to stop early; any other error is propagated. fromMs and toMs are unix ms; pass 0 to disable the respective bound.

type ManagedInbound

type ManagedInbound interface {
	Base() InboundBase
	UserNames() []string
}

type NaiveInbound

type NaiveInbound struct {
	InboundBase
	ListenFields
	Network               string          `json:"network,omitempty"`
	Users                 []NaiveUser     `json:"users"`
	QuicCongestionControl string          `json:"quic_congestion_control,omitempty"`
	TLS                   json.RawMessage `json:"tls,omitempty"`
}

func (*NaiveInbound) Base

func (n *NaiveInbound) Base() InboundBase

func (*NaiveInbound) UserNames

func (n *NaiveInbound) UserNames() []string

type NaiveUser

type NaiveUser struct {
	Username string `json:"username"`
	Password string `json:"password"`
}

type PanelUserInfo

type PanelUserInfo struct {
	Username    string               `json:"username"`
	Permissions PanelUserPermissions `json:"permissions"`
	CreatedAt   int64                `json:"created_at"`
}

PanelUserInfo is a safe (no password hash) representation of a panel user.

type PanelUserPermissions

type PanelUserPermissions struct {
	CanReadUsers        bool `json:"can_read_users"`
	CanWriteUsers       bool `json:"can_write_users"`
	CanReadWireguard    bool `json:"can_read_wireguard"`
	CanWriteWireguard   bool `json:"can_write_wireguard"`
	CanReadConfig       bool `json:"can_read_config"`
	CanWriteConfig      bool `json:"can_write_config"`
	CanReadSettings     bool `json:"can_read_settings"`
	CanWriteSettings    bool `json:"can_write_settings"`
	CanReadPanelUsers   bool `json:"can_read_panel_users"`
	CanWritePanelUsers  bool `json:"can_write_panel_users"`
	CanReadLogs         bool `json:"can_read_logs"`
	CanReadLogsCensored bool `json:"can_read_logs_censored"`
}

PanelUserPermissions holds the set of permissions for a panel user.

func (*PanelUserPermissions) Normalize

func (p *PanelUserPermissions) Normalize()

Normalize keeps granular permissions coherent.

type PeerStats

type PeerStats struct {
	PublicKey       string `json:"public_key"`
	InterfaceName   string `json:"interface_name,omitempty"`
	Endpoint        string `json:"endpoint"`
	LatestHandshake int64  `json:"latest_handshake"`
	TransferRx      int64  `json:"transfer_rx"`
	TransferTx      int64  `json:"transfer_tx"`
}

type RealityConfig

type RealityConfig struct {
	Enabled    bool             `json:"enabled,omitempty"`
	Handshake  RealityHandshake `json:"handshake,omitempty"`
	PrivateKey string           `json:"private_key,omitempty"`
	PublicKey  string           `json:"public_key,omitempty"`
	ShortIDs   []string         `json:"short_id,omitempty"`
}

func (*RealityConfig) UnmarshalJSON

func (r *RealityConfig) UnmarshalJSON(data []byte) error

type RealityHandshake

type RealityHandshake struct {
	Server     string `json:"server,omitempty"`
	ServerPort int    `json:"server_port,omitempty"`
}

type RouteTagRuleResolution

type RouteTagRuleResolution struct {
	Index        int
	Rule         map[string]interface{}
	AuthUsers    []string
	Broken       bool
	BrokenReason string
}

type Sample

type Sample struct {
	User      string
	Timestamp int64
	Uplink    int64
	Downlink  int64
}

type SamplerRun

type SamplerRun struct {
	Timestamp  int64  `json:"timestamp"`
	DurationMs int64  `json:"duration_ms"`
	Inserted   int64  `json:"inserted"`
	Error      string `json:"error"`
	Source     string `json:"source"`
}

type ShadowsocksInbound

type ShadowsocksInbound struct {
	InboundBase
	ListenFields
	Network   []string          `json:"network,omitempty"`
	Method    string            `json:"method"`
	Password  string            `json:"password,omitempty"`
	Users     []ShadowsocksUser `json:"users"`
	Multiplex json.RawMessage   `json:"multiplex,omitempty"`
}

func (*ShadowsocksInbound) Base

func (s *ShadowsocksInbound) Base() InboundBase

func (*ShadowsocksInbound) UserNames

func (s *ShadowsocksInbound) UserNames() []string

type ShadowsocksUser

type ShadowsocksUser struct {
	Name     string `json:"name"`
	Password string `json:"password"`
}

type SingboxClient

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

func NewSingboxClient

func NewSingboxClient(addr string, executor SystemExecutor) *SingboxClient

func (*SingboxClient) Close

func (c *SingboxClient) Close() error

func (*SingboxClient) GetSysStats

func (c *SingboxClient) GetSysStats() (*SysStats, error)

func (*SingboxClient) GetTraffic

func (c *SingboxClient) GetTraffic(inboundTag string) (int64, int64, error)

func (*SingboxClient) GetTrafficMulti

func (c *SingboxClient) GetTrafficMulti(tags []string) (int64, int64, error)

func (*SingboxClient) GetUserTraffic

func (c *SingboxClient) GetUserTraffic(name string) (int64, int64, error)

func (*SingboxClient) QueryUserStats

func (c *SingboxClient) QueryUserStats() (map[string]UserCounter, error)

type SingboxConfig

type SingboxConfig struct {
	Log          json.RawMessage `json:"log,omitempty"`
	DNS          json.RawMessage `json:"dns,omitempty"`
	NTP          json.RawMessage `json:"ntp,omitempty"`
	Certificate  json.RawMessage `json:"certificate,omitempty"`
	Endpoints    json.RawMessage `json:"endpoints,omitempty"`
	Inbounds     json.RawMessage `json:"inbounds,omitempty"`
	Outbounds    json.RawMessage `json:"outbounds,omitempty"`
	Route        json.RawMessage `json:"route,omitempty"`
	Services     json.RawMessage `json:"services,omitempty"`
	Experimental *Experimental   `json:"experimental,omitempty"`
}

type SingboxInboundMeta

type SingboxInboundMeta struct {
	Tag        string `json:"tag"`
	Type       string `json:"type"`
	ListenPort int    `json:"listen_port,omitempty"`
}

type SingboxInboundUserView

type SingboxInboundUserView struct {
	Name     string `json:"name,omitempty"`
	UUID     string `json:"uuid,omitempty"`
	ID       string `json:"id,omitempty"`
	Password string `json:"password,omitempty"`
	Flow     string `json:"flow,omitempty"`
	Security string `json:"security,omitempty"`
	AlterID  int    `json:"alterId,omitempty"`
}

type SingboxInboundView

type SingboxInboundView struct {
	Tag        string                   `json:"tag"`
	Type       string                   `json:"type"`
	ListenPort int                      `json:"listen_port,omitempty"`
	Users      []SingboxInboundUserView `json:"users,omitempty"`
	TLS        *TLSConfig               `json:"-"`
	Raw        map[string]interface{}   `json:"-"`
}

type SingboxOutboundDomainStrategyUpdate

type SingboxOutboundDomainStrategyUpdate struct {
	Tag            string `json:"tag"`
	DomainStrategy string `json:"domain_strategy,omitempty"`
}

type SingboxOutboundView

type SingboxOutboundView struct {
	Tag            string `json:"tag"`
	Type           string `json:"type"`
	Server         string `json:"server,omitempty"`
	ServerPort     int    `json:"server_port,omitempty"`
	DomainStrategy string `json:"domain_strategy,omitempty"`
	DomainResolver string `json:"domain_resolver,omitempty"`
}

type SingboxRestartRequiredError

type SingboxRestartRequiredError struct {
	Reason string
	Err    error
}

func (*SingboxRestartRequiredError) Error

func (*SingboxRestartRequiredError) Unwrap

func (e *SingboxRestartRequiredError) Unwrap() error

type StatsSampler

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

func NewStatsSampler

func NewStatsSampler(sb *SingboxClient, store *Store, cfg *Config) *StatsSampler

func (*StatsSampler) IsPaused

func (s *StatsSampler) IsPaused() bool

func (*StatsSampler) SetPaused

func (s *StatsSampler) SetPaused(p bool)

func (*StatsSampler) Start

func (s *StatsSampler) Start()

func (*StatsSampler) Stop

func (s *StatsSampler) Stop()

func (*StatsSampler) TriggerOnce

func (s *StatsSampler) TriggerOnce()

type Store

type Store struct {
	*sqlcStore.Queries
	// contains filtered or unexported fields
}

func NewStore

func NewStore(dbPath string) (*Store, error)

func (*Store) AddSample

func (s *Store) AddSample(sample Sample) error

func (*Store) BulkInsert

func (s *Store) BulkInsert(samples []Sample) error

func (*Store) Close

func (s *Store) Close() error

func (*Store) CompressOldSamples

func (s *Store) CompressOldSamples(olderThanTs int64) error

func (*Store) CompressOldWGSamples

func (s *Store) CompressOldWGSamples(olderThanTs int64) error

func (*Store) CountSamples

func (s *Store) CountSamples() (int64, error)

func (*Store) CreateAdmin

func (s *Store) CreateAdmin(username, password string) error

func (*Store) CreatePanelUser

func (s *Store) CreatePanelUser(username, password string, perms PanelUserPermissions) error

func (*Store) CreateUserRouteTag

func (s *Store) CreateUserRouteTag(name, color, description, ruleMatchJSON string) (UserRouteTag, error)

func (*Store) DB

func (s *Store) DB() *sql.DB

DB returns the underlying *sql.DB (used by the backup system).

func (*Store) DeleteInboundMeta

func (s *Store) DeleteInboundMeta(tag string) error

func (*Store) DeletePanelUser

func (s *Store) DeletePanelUser(username string) error

func (*Store) DeleteSubscriptionRequest

func (s *Store) DeleteSubscriptionRequest(id int64) error

func (*Store) DeleteSubscriptionRequestsByIDs

func (s *Store) DeleteSubscriptionRequestsByIDs(ids []int64) error

func (*Store) DeleteSubscriptionRequestsBySubID

func (s *Store) DeleteSubscriptionRequestsBySubID(subID int64) error

func (*Store) DeleteUserMetadata

func (s *Store) DeleteUserMetadata(email string) error

func (*Store) DeleteUserRouteTag

func (s *Store) DeleteUserRouteTag(id int64) error

func (*Store) EnforceSubscriptionQuotas

func (s *Store) EnforceSubscriptionQuotas(cfg *Config)

EnforceSubscriptionQuotas evaluates all subscriptions with quota_limit > 0 and bidirectionally enforces them:

  • If total period usage >= quota_limit → disable all assigned users in sing-box.
  • If total period usage < quota_limit → re-enable disabled users and restore them in sing-box.

func (*Store) EnforceUserQuotaNow

func (s *Store) EnforceUserQuotaNow(email string, cfg *Config) error

EnforceUserQuotaNow re-evaluates a single user immediately after an edit. It only disables when the user is currently over quota; re-enable remains owned by the periodic sampler flow so multi-request edit sequences do not race.

func (*Store) EnforceUserQuotas

func (s *Store) EnforceUserQuotas(cfg *Config)

EnforceUserQuotas evaluates all users with individual quota metadata and bidirectionally enforces them against the live sing-box config.

func (*Store) EnsureDefaultAdmin

func (s *Store) EnsureDefaultAdmin() error

func (*Store) EnsureDefaultPanelUser

func (s *Store) EnsureDefaultPanelUser() error

EnsureDefaultPanelUser migrates existing admins to panel_users and/or bootstraps the initial superuser.

func (*Store) GetActiveUserCount

func (s *Store) GetActiveUserCount(duration time.Duration) (int64, error)

func (*Store) GetActiveUserCountWithThreshold

func (s *Store) GetActiveUserCountWithThreshold(duration time.Duration, threshold int64) (int64, error)

func (*Store) GetActiveUsers

func (s *Store) GetActiveUsers(duration time.Duration) ([]string, error)

func (*Store) GetActiveUsersWithThreshold

func (s *Store) GetActiveUsersWithThreshold(duration time.Duration, threshold int64) ([]string, error)

func (*Store) GetAllInboundMeta

func (s *Store) GetAllInboundMeta() (map[string]InboundMeta, error)

func (*Store) GetAllPanelUsers

func (s *Store) GetAllPanelUsers() ([]PanelUserInfo, error)

func (*Store) GetAllUserMetadata

func (s *Store) GetAllUserMetadata() ([]UserMetadata, error)

func (*Store) GetCombinedReport

func (s *Store) GetCombinedReport(user string, start, end int64) ([]Sample, error)

GetCombinedReport queries both daily_usage and samples to build a comprehensive report.

func (*Store) GetDashboardPreferences

func (s *Store) GetDashboardPreferences(ctx context.Context, principal string) (DashboardPreferences, error)

func (*Store) GetGlobalTraffic

func (s *Store) GetGlobalTraffic(start, end int64) ([]TrafficPoint, error)

func (*Store) GetInboundMeta

func (s *Store) GetInboundMeta(tag string) (*InboundMeta, error)

func (*Store) GetLastSeenMap

func (s *Store) GetLastSeenMap() (map[string]int64, error)

func (*Store) GetLastSeenUser

func (s *Store) GetLastSeenUser(user string) (int64, error)

func (*Store) GetLastSeenUserWithTraffic

func (s *Store) GetLastSeenUserWithTraffic(user string) (int64, error)

func (*Store) GetLastSeenWithThreshold

func (s *Store) GetLastSeenWithThreshold(user string, threshold int64) (int64, error)

func (*Store) GetMaxTimestamp

func (s *Store) GetMaxTimestamp() (int64, error)

func (*Store) GetMaxTimestampForUser

func (s *Store) GetMaxTimestampForUser(user string) (int64, error)

func (*Store) GetPanelUserSubscriptionDefaults

func (s *Store) GetPanelUserSubscriptionDefaults(ctx context.Context, username string) (SubscriptionDefaults, error)

func (*Store) GetSBTopTotals

func (s *Store) GetSBTopTotals(start, end int64, limit int) ([]TrafficTotal, error)

GetSBTopTotals aggregates Sing-box usage per user in the range.

func (*Store) GetSBTrafficBuckets

func (s *Store) GetSBTrafficBuckets(start, end, interval int64) (map[int64]TrafficStats, error)

GetSBTrafficBuckets aggregates Sing-box traffic per time bucket.

func (*Store) GetSBUserTrafficBuckets

func (s *Store) GetSBUserTrafficBuckets(user string, start, end, interval int64) (map[int64]TrafficStats, error)

func (*Store) GetSamplerRuns

func (s *Store) GetSamplerRuns(limit, offset int) ([]SamplerRun, error)

func (*Store) GetSamples

func (s *Store) GetSamples(user string, start, end int64) ([]Sample, error)

func (*Store) GetSubscriptionHappConfig

func (s *Store) GetSubscriptionHappConfig(ctx context.Context) (SubscriptionHappConfig, error)

func (*Store) GetTrafficPerUser

func (s *Store) GetTrafficPerUser(start, end int64) (map[string]TrafficStats, error)

GetTrafficPerUser returns aggregated usage per user for the given time range.

func (*Store) GetUserMetadata

func (s *Store) GetUserMetadata(email string) (*UserMetadata, error)

func (*Store) GetUserRouteTag

func (s *Store) GetUserRouteTag(id int64) (*UserRouteTag, error)

func (*Store) GetUsers

func (s *Store) GetUsers() ([]User, error)

GetUsers returns all users.

func (*Store) GetWGPeerMeta

func (s *Store) GetWGPeerMeta() (map[string]WGPeerMeta, error)

func (*Store) GetWGTopTotals

func (s *Store) GetWGTopTotals(start, end int64, limit int) ([]TrafficTotal, error)

GetWGTopTotals aggregates total usage per peer (rx/tx deltas) in the given range.

func (*Store) GetWGTrafficBuckets

func (s *Store) GetWGTrafficBuckets(publicKeys []string, start, end, interval int64) (map[int64]TrafficStats, error)

GetWGTrafficBuckets returns aggregated WireGuard traffic deltas bucketed by interval. It computes per-sample deltas using window functions, then sums them per bucket.

func (*Store) GetWGTrafficDelta

func (s *Store) GetWGTrafficDelta(publicKey string, start, end int64) (int64, int64, error)

GetWGTrafficDelta returns rx/tx delta between first and last sample in the range.

func (*Store) GetWGTrafficSeries

func (s *Store) GetWGTrafficSeries(publicKey string, start, end int64, limit int) ([]WGSample, error)

func (*Store) HasSamples

func (s *Store) HasSamples() (bool, error)

func (*Store) InsertWGSamples

func (s *Store) InsertWGSamples(samples []WGSample) error

func (*Store) ListUserRouteTags

func (s *Store) ListUserRouteTags() ([]UserRouteTag, error)

func (*Store) LogSamplerRun

func (s *Store) LogSamplerRun(ts int64, durationMs int64, inserted int64, errStr string, source string)

func (*Store) PruneOlderThan

func (s *Store) PruneOlderThan(ts int64) error

func (*Store) PruneSubscriptionRequestsOlderThan

func (s *Store) PruneSubscriptionRequestsOlderThan(ts int64) error

func (*Store) PruneWGSamplesOlderThan

func (s *Store) PruneWGSamplesOlderThan(ts int64) error

func (*Store) ReconcileUserQuotaNow

func (s *Store) ReconcileUserQuotaNow(email string, cfg *Config) error

func (*Store) RemoveUserFromSubscriptions

func (s *Store) RemoveUserFromSubscriptions(email string) error

func (*Store) RenameInboundMeta

func (s *Store) RenameInboundMeta(oldTag, newTag string) error

func (*Store) RenameInboundReferences

func (s *Store) RenameInboundReferences(oldTag, newTag string) error

func (*Store) RenameUserTrafficIdentity

func (s *Store) RenameUserTrafficIdentity(oldName, newName string) error

func (*Store) RunWGSampleTx

func (s *Store) RunWGSampleTx(handshakes map[string]int64, samples []WGSample) error

RunWGSampleTx persists a WireGuard sampling batch atomically: updates peer handshake timestamps and inserts new traffic samples in a single transaction.

func (*Store) SaveInboundMeta

func (s *Store) SaveInboundMeta(meta InboundMeta) error

func (*Store) SaveUserMetadata

func (s *Store) SaveUserMetadata(meta UserMetadata) error

func (*Store) TruncateSamples

func (s *Store) TruncateSamples() error

func (*Store) UpdateAdminPassword

func (s *Store) UpdateAdminPassword(username, newPassword string) error

func (*Store) UpdateAdminUsername

func (s *Store) UpdateAdminUsername(oldUsername, newUsername string) error

func (*Store) UpdateDashboardPreferences

func (s *Store) UpdateDashboardPreferences(ctx context.Context, principal string, prefs DashboardPreferences) error

func (*Store) UpdatePanelUserPassword

func (s *Store) UpdatePanelUserPassword(username, newPassword string) error

func (*Store) UpdatePanelUserPermissions

func (s *Store) UpdatePanelUserPermissions(username string, perms PanelUserPermissions) error

func (*Store) UpdatePanelUserSubscriptionDefaults

func (s *Store) UpdatePanelUserSubscriptionDefaults(ctx context.Context, username string, defaults SubscriptionDefaults) error

func (*Store) UpdatePanelUsername

func (s *Store) UpdatePanelUsername(oldUsername, newUsername string) error

func (*Store) UpdateSubscriptionHappConfig

func (s *Store) UpdateSubscriptionHappConfig(ctx context.Context, config SubscriptionHappConfig) error

func (*Store) UpdateUserRouteTag

func (s *Store) UpdateUserRouteTag(tag UserRouteTag) error

func (*Store) UpdateWGPeerHandshakes

func (s *Store) UpdateWGPeerHandshakes(handshakes map[string]int64) error

func (*Store) UpsertWGPeer

func (s *Store) UpsertWGPeer(publicKey, alias string, deleted bool) error

func (*Store) Vacuum

func (s *Store) Vacuum() error

func (*Store) VerifyAdmin

func (s *Store) VerifyAdmin(username, password string) (bool, error)

func (*Store) VerifyPanelUser

func (s *Store) VerifyPanelUser(username, password string) (*PanelUserPermissions, error)

VerifyPanelUser checks credentials and returns the user's permissions if valid.

type SubscriptionDefaults

type SubscriptionDefaults struct {
	ProfileUpdateIntervalHours *int64   `json:"profile_update_interval_hours"`
	UpdateAlways               bool     `json:"update_always"`
	Destinations               []string `json:"destinations"`
}

type SubscriptionHappConfig

type SubscriptionHappConfig struct {
	ProviderID         string                      `json:"provider_id"`
	HideSettings       string                      `json:"hide_settings"`
	AlwaysHWID         string                      `json:"subscription_always_hwid_enable"`
	AutoUpdateOnOpen   string                      `json:"subscription_auto_update_open_enable"`
	PingOnOpen         string                      `json:"subscription_ping_onopen_enabled"`
	ColorProfile       string                      `json:"color_profile"`
	ProfileFlag        string                      `json:"profile_flag"`
	RoutingProfile     string                      `json:"routing_profile"`
	AdvancedParameters []SubscriptionHappParameter `json:"advanced_parameters"`
}

type SubscriptionHappParameter

type SubscriptionHappParameter struct {
	Key   string `json:"key"`
	Value string `json:"value"`
}

type SubscriptionProtectionConfig

type SubscriptionProtectionConfig struct {
	MaxRequests                int  `json:"max_requests"`
	WindowSeconds              int  `json:"window_seconds"`
	UAFilterEnabled            bool `json:"ua_filter_enabled"`
	SocialFetchersBlockEnabled bool `json:"social_fetchers_block_enabled"`
}

type SysStats

type SysStats struct {
	NumGoroutine uint32 `json:"num_goroutine"`
	NumGC        uint32 `json:"num_gc"`
	Alloc        uint64 `json:"alloc"`
	TotalAlloc   uint64 `json:"total_alloc"`
	Sys          uint64 `json:"sys"`
	Mallocs      uint64 `json:"mallocs"`
	Frees        uint64 `json:"frees"`
	LiveObjects  uint64 `json:"live_objects"`
	PauseTotalNs uint64 `json:"pause_total_ns"`
	Uptime       uint32 `json:"uptime"`
}

type SystemExecutor

type SystemExecutor interface {
	// Service Management
	RestartService(ctx context.Context, name string) error
	StartService(ctx context.Context, name string) error
	StopService(ctx context.Context, name string) error
	IsServiceActive(ctx context.Context, name string) (bool, error)

	// File Management (Atomic Operations where possible)
	// WriteConfig writes content to the specified path.
	// Implementation should ensure atomic writes or safe replacements.
	WriteConfig(ctx context.Context, path string, content []byte, fileMode os.FileMode) error
	// ReadConfig reads content from the specified path.
	ReadConfig(ctx context.Context, path string) ([]byte, error)

	// Sysctl Management
	// ApplySysctl sets a kernel parameter. Implementation MUST enforce a whitelist.
	ApplySysctl(ctx context.Context, key, value string) error
	// GetSysctl retrieves a kernel parameter. Implementation MUST enforce a whitelist.
	GetSysctl(ctx context.Context, key string) (string, error)

	// SyncWireGuard applies the WireGuard configuration to the interface.
	SyncWireGuard(ctx context.Context, interfaceName string, configContent []byte) error
	// RestartWireGuard restarts the target WireGuard interface service.
	RestartWireGuard(ctx context.Context, interfaceName string) error
	// ListWireGuardInterfaces returns currently available WireGuard interface names.
	ListWireGuardInterfaces(ctx context.Context) ([]string, error)
	// EnableWireGuardInterface brings the target interface up.
	EnableWireGuardInterface(ctx context.Context, interfaceName string) error
	// DisableWireGuardInterface brings the target interface down.
	DisableWireGuardInterface(ctx context.Context, interfaceName string) error

	// ValidateSingboxConfig validates the sing-box configuration content.
	ValidateSingboxConfig(ctx context.Context, content []byte) error

	// GetWireGuardStats retrieves WireGuard peer statistics.
	GetWireGuardStats(ctx context.Context) (map[string]PeerStats, error)

	// Lifecycle
	// CheckConnectivity verifies if the underlying system is reachable.
	CheckConnectivity(ctx context.Context) error
	// Close releases any resources held by the executor.
	Close() error

	// Network
	// Dial creates a connection to the address on the target system.
	Dial(ctx context.Context, network, addr string) (net.Conn, error)
}

SystemExecutor defines the interface for system-level operations. It abstracts local host execution strategies (local, docker_local).

type SystemStats

type SystemStats struct {
	History []TrafficPoint
	// contains filtered or unexported fields
}

func (*SystemStats) AddPoint

func (s *SystemStats) AddPoint(up, down int64)

func (*SystemStats) GetHistory

func (s *SystemStats) GetHistory(duration time.Duration) []TrafficPoint

type TLSConfig

type TLSConfig struct {
	Enabled         bool           `json:"enabled,omitempty"`
	ServerName      string         `json:"server_name,omitempty"`
	ALPN            []string       `json:"alpn,omitempty"`
	CertificatePath string         `json:"certificate_path,omitempty"`
	Reality         *RealityConfig `json:"reality,omitempty"`
}

type TrafficPoint

type TrafficPoint struct {
	Timestamp int64 `json:"timestamp"`
	Uplink    int64 `json:"uplink"`
	Downlink  int64 `json:"downlink"`
}

type TrafficStats

type TrafficStats struct {
	Uplink   int64
	Downlink int64
}

type TrafficTotal

type TrafficTotal struct {
	Key   string
	Total int64
	Rx    int64
	Tx    int64
}

WGPubTotal represents aggregated wireguard usage for a peer.

type TrojanInbound

type TrojanInbound struct {
	InboundBase
	ListenFields
	Users     []TrojanUser    `json:"users"`
	TLS       json.RawMessage `json:"tls,omitempty"`
	Multiplex json.RawMessage `json:"multiplex,omitempty"`
	Transport json.RawMessage `json:"transport,omitempty"`
}

func (*TrojanInbound) Base

func (t *TrojanInbound) Base() InboundBase

func (*TrojanInbound) UserNames

func (t *TrojanInbound) UserNames() []string

type TrojanUser

type TrojanUser struct {
	Name     string `json:"name"`
	Password string `json:"password"` // NOT uuid - Trojan uses password
}

type User

type User struct {
	Uuid        string
	Username    string
	DataLimit   int64
	QuotaPeriod string
	ResetDay    int
	Enabled     bool
}

type UserAccount

type UserAccount struct {
	Name          string   `json:"name"`
	UUID          string   `json:"uuid"`
	Flow          string   `json:"flow"`
	VmessSecurity string   `json:"vmess_security,omitempty"`
	VmessAlterID  int      `json:"vmess_alter_id,omitempty"`
	InboundTags   []string `json:"inbound_tags"`
}

type UserCounter

type UserCounter struct {
	Uplink   int64
	Downlink int64
}

type UserInboundInfo

type UserInboundInfo struct {
	Tag           string `json:"tag"`
	UUID          string `json:"uuid"`
	Password      string `json:"password,omitempty"`
	Flow          string `json:"flow,omitempty"`
	VmessSecurity string `json:"vmess_security,omitempty"`
	VmessAlterID  int    `json:"vmess_alter_id,omitempty"`
}

type UserMetadata

type UserMetadata struct {
	Email         string   `json:"email"`
	QuotaLimit    int64    `json:"quota_limit"`
	QuotaPeriod   string   `json:"quota_period"`
	ResetDay      int      `json:"reset_day"`
	Enabled       bool     `json:"enabled"`
	Credential    string   `json:"credential,omitempty"`
	Flow          string   `json:"flow,omitempty"`
	VmessSecurity string   `json:"vmess_security,omitempty"`
	VmessAlterID  int      `json:"vmess_alter_id,omitempty"`
	InboundTags   []string `json:"inbound_tags,omitempty"`
}

type UserRouteTag

type UserRouteTag struct {
	ID            int64  `json:"id"`
	Name          string `json:"name"`
	Color         string `json:"color"`
	Description   string `json:"description"`
	RuleMatchJSON string `json:"rule_match_json"`
	CreatedAt     int64  `json:"created_at"`
	UpdatedAt     int64  `json:"updated_at"`
}

type V2RayAPI

type V2RayAPI struct {
	Listen string      `json:"listen,omitempty"`
	Stats  *V2RayStats `json:"stats,omitempty"`
}

type V2RayStats

type V2RayStats struct {
	Enabled   bool     `json:"enabled"` // NO omitempty - must always be written explicitly
	Inbounds  []string `json:"inbounds,omitempty"`
	Outbounds []string `json:"outbounds,omitempty"`
	Users     []string `json:"users,omitempty"`
}

type VlessInbound

type VlessInbound struct {
	InboundBase
	ListenFields
	Users     []VlessUser     `json:"users"`
	TLS       json.RawMessage `json:"tls,omitempty"`
	Multiplex json.RawMessage `json:"multiplex,omitempty"`
	Transport json.RawMessage `json:"transport,omitempty"`
}

func (*VlessInbound) Base

func (v *VlessInbound) Base() InboundBase

func (*VlessInbound) UserNames

func (v *VlessInbound) UserNames() []string

type VlessUser

type VlessUser struct {
	Name string `json:"name"`
	UUID string `json:"uuid"`
	Flow string `json:"flow,omitempty"` // "xtls-rprx-vision" or empty
}

type VmessInbound

type VmessInbound struct {
	InboundBase
	ListenFields
	Users     []VmessUser     `json:"users"`
	TLS       json.RawMessage `json:"tls,omitempty"`
	Multiplex json.RawMessage `json:"multiplex,omitempty"`
	Transport json.RawMessage `json:"transport,omitempty"`
}

func (*VmessInbound) Base

func (v *VmessInbound) Base() InboundBase

func (*VmessInbound) UserNames

func (v *VmessInbound) UserNames() []string

type VmessUser

type VmessUser struct {
	Name    string `json:"name"`
	UUID    string `json:"uuid"`
	AlterID int    `json:"alterId,omitempty"`
}

func (*VmessUser) UnmarshalJSON

func (u *VmessUser) UnmarshalJSON(data []byte) error

type WGDailyUsage

type WGDailyUsage struct {
	PublicKey string
	Timestamp int64
	Rx        int64
	Tx        int64
}

WGDailyUsage represents aggregated traffic data for a WG peer on a specific bucket (8h).

type WGPeerMeta

type WGPeerMeta struct {
	PublicKey     string
	Alias         string
	LastHandshake int64
	Deleted       bool
}

type WGSample

type WGSample struct {
	PublicKey string `json:"public_key"`
	Timestamp int64  `json:"timestamp"`
	Rx        int64  `json:"rx"`
	Tx        int64  `json:"tx"`
	Endpoint  string `json:"endpoint"`
}

type WireGuardConfig

type WireGuardConfig struct {
	Interface WireGuardInterface
	Peers     []WireGuardPeer
	Path      string
}

func LoadWireGuardConfig

func LoadWireGuardConfig(path string) (*WireGuardConfig, error)

func (*WireGuardConfig) AddPeer

func (c *WireGuardConfig) AddPeer(peer WireGuardPeer) error

func (*WireGuardConfig) RemovePeer

func (c *WireGuardConfig) RemovePeer(publicKey string) error

func (*WireGuardConfig) Save

func (c *WireGuardConfig) Save() error

func (*WireGuardConfig) UpdateInterface

func (c *WireGuardConfig) UpdateInterface(updated WireGuardInterface) error

func (*WireGuardConfig) UpdatePeer

func (c *WireGuardConfig) UpdatePeer(publicKey string, updated WireGuardPeer) error

type WireGuardInterface

type WireGuardInterface struct {
	Address     string `json:"address"`
	BindAddress string `json:"bind_address,omitempty"`
	PrivateKey  string `json:"private_key"`
	ListenPort  int    `json:"listen_port"`
	PostUp      string `json:"post_up,omitempty"`
	PostDown    string `json:"post_down,omitempty"`
	MTU         int    `json:"mtu,omitempty"`
	DNS         string `json:"dns,omitempty"`
	PublicKey   string `json:"public_key,omitempty"`
}

type WireGuardPeer

type WireGuardPeer struct {
	PublicKey    string `json:"public_key"`
	PrivateKey   string `json:"private_key,omitempty"`
	AllowedIPs   string `json:"allowed_ips"`
	Endpoint     string `json:"endpoint,omitempty"`
	Alias        string `json:"alias,omitempty"`
	Email        string `json:"email,omitempty"`
	PresharedKey string `json:"preshared_key,omitempty"`
}

type WireGuardRegistry

type WireGuardRegistry struct{}

func (WireGuardRegistry) DiscoverInterfaces

func (r WireGuardRegistry) DiscoverInterfaces(dir string) ([]string, error)

func (WireGuardRegistry) InterfacePath

func (WireGuardRegistry) InterfacePath(dir, name string) (string, error)

func (WireGuardRegistry) LoadInterface

func (r WireGuardRegistry) LoadInterface(dir, name string) (*WireGuardConfig, error)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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