Documentation
¶
Index ¶
- Variables
- func AuditDBPathFor(mainDBPath string) string
- func BackupDBToTarGz(ctx context.Context, db *sql.DB, archiveName, destPath string) error
- func BackupDBWithColdToTarGz(ctx context.Context, db *sql.DB, archiveName, destPath string, ...) error
- func CanonicalRouteTagRuleMatch(rule map[string]interface{}) (string, error)
- func CensorLine(line string) string
- func DetectPublicIP() string
- func GenerateWireGuardKeys() (string, string, error)
- func GetWireGuardStats() (map[string]PeerStats, error)
- func LogDBPathFor(mainDBPath string) string
- func QuotaWindowStart(period string, now time.Time) int64
- func SanitiseManagedInboundFields(inbound map[string]interface{})
- func SubscriptionUsageWindowStart(period string, now time.Time) int64
- type AnyTLSInbound
- type AnyTLSUser
- type AuditEntry
- type AuditLogPage
- type AuditStore
- func (a *AuditStore) Close()
- func (a *AuditStore) DB() *sql.DB
- func (a *AuditStore) InsertAuditLog(ctx context.Context, e AuditEntry) error
- func (a *AuditStore) PruneToSize(maxBytes int64)
- func (a *AuditStore) QueryAuditLog(ctx context.Context, limit, offset int, domain, action string) (AuditLogPage, error)
- func (a *AuditStore) SizeBytes() int64
- type Calculator
- type ClashAPI
- type Config
- func (c *Config) AddSingboxInbound(newInbound map[string]interface{}) error
- func (c *Config) AddUser(name, uuid, flow, inboundTag, vmessSecurity string, vmessAlterID int) error
- func (c *Config) ApplySingboxChanges() error
- func (c *Config) ApplyWireGuardTestModeDefaults()
- func (c *Config) ClearSingboxPendingChanges()
- func (c *Config) DeleteSingboxInbound(tag string) error
- func (c *Config) DetectPortCollision(content []byte) error
- func (c *Config) GetActiveUsers() ([]UserAccount, error)
- func (c *Config) GetSingboxConfig() (string, error)
- func (c *Config) GetSingboxConfigMap() (map[string]interface{}, error)
- func (c *Config) GetSingboxDNS() (map[string]interface{}, error)
- func (c *Config) GetSingboxInboundByTag(tag string) (map[string]interface{}, error)
- func (c *Config) GetSingboxInboundMeta(tag string) (*SingboxInboundMeta, error)
- func (c *Config) GetSingboxInboundMetas() ([]SingboxInboundMeta, error)
- func (c *Config) GetSingboxInboundView(tag string) (*SingboxInboundView, error)
- func (c *Config) GetSingboxInboundViews() ([]SingboxInboundView, error)
- func (c *Config) GetSingboxInbounds() ([]map[string]interface{}, error)
- func (c *Config) GetSingboxOutboundViews() ([]SingboxOutboundView, error)
- func (c *Config) GetSingboxPendingChanges() bool
- func (c *Config) GetSingboxRouteRules() ([]map[string]interface{}, error)
- func (c *Config) GetUserInbounds(name string) ([]UserInboundInfo, error)
- func (c *Config) MarkSingboxPending()
- func (c *Config) ModifySingboxConfig(modifier func(*SingboxConfig) error) error
- func (c *Config) ReloadSingbox() error
- func (c *Config) RemoveInboundFromLists(tag string) error
- func (c *Config) RemoveUser(name string) error
- func (c *Config) RemoveUserFromInbound(name, inboundTag string) error
- func (c *Config) RenameInboundInLists(oldTag, newTag string) error
- func (c *Config) RenameUser(originalName, newName, uuid, flow, vmessSecurity string, vmessAlterID int) error
- func (c *Config) ReplaceSingboxRouteRules(rules []map[string]interface{}) error
- func (c *Config) ResolveRouteTagRule(ruleMatchJSON string) (RouteTagRuleResolution, error)
- func (c *Config) ResolveUserRouteTags(userName string, tags []UserRouteTag) ([]UserRouteTag, error)
- func (c *Config) SaveAppConfig() error
- func (c *Config) SetExecutor(exec SystemExecutor)
- func (c *Config) SyncInboundsFromSingbox() error
- func (c *Config) UpdateSingboxConfig(content string) error
- func (c *Config) UpdateSingboxDNS(dns map[string]interface{}) error
- func (c *Config) UpdateSingboxInbound(tag string, updatedInbound map[string]interface{}) error
- func (c *Config) UpdateSingboxOutboundDomainStrategies(updates []SingboxOutboundDomainStrategyUpdate) error
- func (c *Config) UpdateUser(name, uuid, flow, inboundTag, vmessSecurity string, vmessAlterID int) error
- func (c *Config) UpdateUserInInbound(name, uuid, flow, inboundTag, vmessSecurity string, vmessAlterID int) error
- func (c *Config) UpdateUserRouteTagMembership(userName string, targetTagIDs []int64, tags []UserRouteTag) ([]UserRouteTag, error)
- func (c *Config) UpsertSingboxRouteRules(newRules []map[string]interface{}) error
- func (c *Config) ValidateConfig(content []byte) error
- type DailyUsage
- type DashboardPreferences
- type Experimental
- type Hysteria2Inbound
- type Hysteria2Obfs
- type Hysteria2User
- type InboundBase
- type InboundMeta
- type ListenFields
- type LogIngester
- type LogRow
- type LogSegment
- type LogStore
- func (l *LogStore) CheckRetention(ctx context.Context, mode string, maxMB, days int, unit, coldDir string) (*LogSegment, error)
- func (l *LogStore) Close()
- func (l *LogStore) DB() *sql.DB
- func (l *LogStore) ExportToCold(ctx context.Context, coldDir string, maxID int64) (*LogSegment, error)
- func (l *LogStore) HotDateRange(ctx context.Context) (firstMs, lastMs int64, err error)
- func (l *LogStore) InsertLogs(ctx context.Context, ts int64, lines []string) error
- func (l *LogStore) ListSegments(ctx context.Context, limit int) ([]LogSegment, error)
- func (l *LogStore) OldestHotTs(ctx context.Context) (int64, error)
- func (l *LogStore) PollAfterID(ctx context.Context, afterID int64, limit int) ([]LogRow, error)
- func (l *LogStore) RowCount(ctx context.Context) (int64, error)
- func (l *LogStore) SegmentStats(ctx context.Context) (count int64, totalBytes int64, err error)
- func (l *LogStore) SegmentsInRange(ctx context.Context, fromMs, toMs int64) ([]LogSegment, error)
- func (l *LogStore) SizeBytes() int64
- func (l *LogStore) TailHot(ctx context.Context, limit int) ([]LogRow, error)
- func (l *LogStore) WalkHot(ctx context.Context, simpleText string, fromMs, toMs int64, ...) error
- type ManagedInbound
- type NaiveInbound
- type NaiveUser
- type PanelUserInfo
- type PanelUserPermissions
- type PeerStats
- type RealityConfig
- type RealityHandshake
- type RouteTagRuleResolution
- type Sample
- type SamplerRun
- type ShadowsocksInbound
- type ShadowsocksUser
- type SingboxClient
- func (c *SingboxClient) Close() error
- func (c *SingboxClient) GetSysStats() (*SysStats, error)
- func (c *SingboxClient) GetTraffic(inboundTag string) (int64, int64, error)
- func (c *SingboxClient) GetTrafficMulti(tags []string) (int64, int64, error)
- func (c *SingboxClient) GetUserTraffic(name string) (int64, int64, error)
- func (c *SingboxClient) QueryUserStats() (map[string]UserCounter, error)
- type SingboxConfig
- type SingboxInboundMeta
- type SingboxInboundUserView
- type SingboxInboundView
- type SingboxOutboundDomainStrategyUpdate
- type SingboxOutboundView
- type SingboxRestartRequiredError
- type StatsSampler
- type Store
- func (s *Store) AddSample(sample Sample) error
- func (s *Store) BulkInsert(samples []Sample) error
- func (s *Store) Close() error
- func (s *Store) CompressOldSamples(olderThanTs int64) error
- func (s *Store) CompressOldWGSamples(olderThanTs int64) error
- func (s *Store) CountSamples() (int64, error)
- func (s *Store) CreateAdmin(username, password string) error
- func (s *Store) CreatePanelUser(username, password string, perms PanelUserPermissions) error
- func (s *Store) CreateUserRouteTag(name, color, description, ruleMatchJSON string) (UserRouteTag, error)
- func (s *Store) DB() *sql.DB
- func (s *Store) DeleteInboundMeta(tag string) error
- func (s *Store) DeletePanelUser(username string) error
- func (s *Store) DeleteSubscriptionRequest(id int64) error
- func (s *Store) DeleteSubscriptionRequestsByIDs(ids []int64) error
- func (s *Store) DeleteSubscriptionRequestsBySubID(subID int64) error
- func (s *Store) DeleteUserMetadata(email string) error
- func (s *Store) DeleteUserRouteTag(id int64) error
- func (s *Store) EnforceSubscriptionQuotas(cfg *Config)
- func (s *Store) EnforceUserQuotaNow(email string, cfg *Config) error
- func (s *Store) EnforceUserQuotas(cfg *Config)
- func (s *Store) EnsureDefaultAdmin() error
- func (s *Store) EnsureDefaultPanelUser() error
- func (s *Store) GetActiveUserCount(duration time.Duration) (int64, error)
- func (s *Store) GetActiveUserCountWithThreshold(duration time.Duration, threshold int64) (int64, error)
- func (s *Store) GetActiveUsers(duration time.Duration) ([]string, error)
- func (s *Store) GetActiveUsersWithThreshold(duration time.Duration, threshold int64) ([]string, error)
- func (s *Store) GetAllInboundMeta() (map[string]InboundMeta, error)
- func (s *Store) GetAllPanelUsers() ([]PanelUserInfo, error)
- func (s *Store) GetAllUserMetadata() ([]UserMetadata, error)
- func (s *Store) GetCombinedReport(user string, start, end int64) ([]Sample, error)
- func (s *Store) GetDashboardPreferences(ctx context.Context, principal string) (DashboardPreferences, error)
- func (s *Store) GetGlobalTraffic(start, end int64) ([]TrafficPoint, error)
- func (s *Store) GetInboundMeta(tag string) (*InboundMeta, error)
- func (s *Store) GetLastSeenMap() (map[string]int64, error)
- func (s *Store) GetLastSeenUser(user string) (int64, error)
- func (s *Store) GetLastSeenUserWithTraffic(user string) (int64, error)
- func (s *Store) GetLastSeenWithThreshold(user string, threshold int64) (int64, error)
- func (s *Store) GetMaxTimestamp() (int64, error)
- func (s *Store) GetMaxTimestampForUser(user string) (int64, error)
- func (s *Store) GetPanelUserSubscriptionDefaults(ctx context.Context, username string) (SubscriptionDefaults, error)
- func (s *Store) GetSBTopTotals(start, end int64, limit int) ([]TrafficTotal, error)
- func (s *Store) GetSBTrafficBuckets(start, end, interval int64) (map[int64]TrafficStats, error)
- func (s *Store) GetSBUserTrafficBuckets(user string, start, end, interval int64) (map[int64]TrafficStats, error)
- func (s *Store) GetSamplerRuns(limit, offset int) ([]SamplerRun, error)
- func (s *Store) GetSamples(user string, start, end int64) ([]Sample, error)
- func (s *Store) GetSubscriptionHappConfig(ctx context.Context) (SubscriptionHappConfig, error)
- func (s *Store) GetTrafficPerUser(start, end int64) (map[string]TrafficStats, error)
- func (s *Store) GetUserMetadata(email string) (*UserMetadata, error)
- func (s *Store) GetUserRouteTag(id int64) (*UserRouteTag, error)
- func (s *Store) GetUsers() ([]User, error)
- func (s *Store) GetWGPeerMeta() (map[string]WGPeerMeta, error)
- func (s *Store) GetWGTopTotals(start, end int64, limit int) ([]TrafficTotal, error)
- func (s *Store) GetWGTrafficBuckets(publicKeys []string, start, end, interval int64) (map[int64]TrafficStats, error)
- func (s *Store) GetWGTrafficDelta(publicKey string, start, end int64) (int64, int64, error)
- func (s *Store) GetWGTrafficSeries(publicKey string, start, end int64, limit int) ([]WGSample, error)
- func (s *Store) HasSamples() (bool, error)
- func (s *Store) InsertWGSamples(samples []WGSample) error
- func (s *Store) ListUserRouteTags() ([]UserRouteTag, error)
- func (s *Store) LogSamplerRun(ts int64, durationMs int64, inserted int64, errStr string, source string)
- func (s *Store) PruneOlderThan(ts int64) error
- func (s *Store) PruneSubscriptionRequestsOlderThan(ts int64) error
- func (s *Store) PruneWGSamplesOlderThan(ts int64) error
- func (s *Store) ReconcileUserQuotaNow(email string, cfg *Config) error
- func (s *Store) RemoveUserFromSubscriptions(email string) error
- func (s *Store) RenameInboundMeta(oldTag, newTag string) error
- func (s *Store) RenameInboundReferences(oldTag, newTag string) error
- func (s *Store) RenameUserTrafficIdentity(oldName, newName string) error
- func (s *Store) RunWGSampleTx(handshakes map[string]int64, samples []WGSample) error
- func (s *Store) SaveInboundMeta(meta InboundMeta) error
- func (s *Store) SaveUserMetadata(meta UserMetadata) error
- func (s *Store) TruncateSamples() error
- func (s *Store) UpdateAdminPassword(username, newPassword string) error
- func (s *Store) UpdateAdminUsername(oldUsername, newUsername string) error
- func (s *Store) UpdateDashboardPreferences(ctx context.Context, principal string, prefs DashboardPreferences) error
- func (s *Store) UpdatePanelUserPassword(username, newPassword string) error
- func (s *Store) UpdatePanelUserPermissions(username string, perms PanelUserPermissions) error
- func (s *Store) UpdatePanelUserSubscriptionDefaults(ctx context.Context, username string, defaults SubscriptionDefaults) error
- func (s *Store) UpdatePanelUsername(oldUsername, newUsername string) error
- func (s *Store) UpdateSubscriptionHappConfig(ctx context.Context, config SubscriptionHappConfig) error
- func (s *Store) UpdateUserRouteTag(tag UserRouteTag) error
- func (s *Store) UpdateWGPeerHandshakes(handshakes map[string]int64) error
- func (s *Store) UpsertWGPeer(publicKey, alias string, deleted bool) error
- func (s *Store) Vacuum() error
- func (s *Store) VerifyAdmin(username, password string) (bool, error)
- func (s *Store) VerifyPanelUser(username, password string) (*PanelUserPermissions, error)
- type SubscriptionDefaults
- type SubscriptionHappConfig
- type SubscriptionHappParameter
- type SubscriptionProtectionConfig
- type SysStats
- type SystemExecutor
- type SystemStats
- type TLSConfig
- type TrafficPoint
- type TrafficStats
- type TrafficTotal
- type TrojanInbound
- type TrojanUser
- type User
- type UserAccount
- type UserCounter
- type UserInboundInfo
- type UserMetadata
- type UserRouteTag
- type V2RayAPI
- type V2RayStats
- type VlessInbound
- type VlessUser
- type VmessInbound
- type VmessUser
- type WGDailyUsage
- type WGPeerMeta
- type WGSample
- type WireGuardConfig
- func (c *WireGuardConfig) AddPeer(peer WireGuardPeer) error
- func (c *WireGuardConfig) RemovePeer(publicKey string) error
- func (c *WireGuardConfig) Save() error
- func (c *WireGuardConfig) UpdateInterface(updated WireGuardInterface) error
- func (c *WireGuardConfig) UpdatePeer(publicKey string, updated WireGuardPeer) error
- type WireGuardInterface
- type WireGuardPeer
- type WireGuardRegistry
Constants ¶
This section is empty.
Variables ¶
var ErrStopLogWalk = errors.New("stop log walk")
ErrStopLogWalk is returned by a WalkHot visitor to stop iteration early.
var ErrUserAssignedToAnotherInbound = errors.New("user is already assigned to another inbound")
var Stats = &SystemStats{ History: make([]TrafficPoint, 0), }
Functions ¶
func AuditDBPathFor ¶
AuditDBPathFor derives the audit DB path from the main DB path. e.g. "data/stats.db" → "data/audit.db"
func BackupDBToTarGz ¶
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 CensorLine ¶
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 GetWireGuardStats ¶
func LogDBPathFor ¶
LogDBPathFor derives the log DB path from the main DB path. e.g. "data/stats.db" → "data/singbox_logs.db"
func QuotaWindowStart ¶
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.
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 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 (*ClashAPI) UnmarshalJSON ¶
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 (*Config) AddSingboxInbound ¶
AddSingboxInbound appends a new inbound block
func (*Config) ApplySingboxChanges ¶
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 ¶
DeleteSingboxInbound removes an inbound by tag
func (*Config) DetectPortCollision ¶
DetectPortCollision parses the config and checks for overlapping ports in inbounds
func (*Config) GetActiveUsers ¶
func (c *Config) GetActiveUsers() ([]UserAccount, error)
func (*Config) GetSingboxConfig ¶
GetSingboxConfig reads the raw config file content
func (*Config) GetSingboxConfigMap ¶
GetSingboxConfigMap reads the raw config file content as a map
func (*Config) GetSingboxDNS ¶
func (*Config) GetSingboxInboundByTag ¶
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 ¶
GetSingboxInbounds returns the list of inbounds as map objects.
func (*Config) GetSingboxOutboundViews ¶
func (c *Config) GetSingboxOutboundViews() ([]SingboxOutboundView, error)
func (*Config) GetSingboxPendingChanges ¶
func (*Config) GetSingboxRouteRules ¶
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 (*Config) RemoveInboundFromLists ¶
RemoveInboundFromLists removes an inbound tag from managed_inbounds and stats_inbounds
func (*Config) RemoveUser ¶
func (*Config) RemoveUserFromInbound ¶
func (*Config) RenameInboundInLists ¶
RenameInboundInLists updates an inbound tag in managed_inbounds and stats_inbounds
func (*Config) RenameUser ¶
func (*Config) ReplaceSingboxRouteRules ¶
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 (*Config) SetExecutor ¶
func (c *Config) SetExecutor(exec SystemExecutor)
func (*Config) SyncInboundsFromSingbox ¶
func (*Config) UpdateSingboxConfig ¶
UpdateSingboxConfig writes raw content to config file and restarts service
func (*Config) UpdateSingboxDNS ¶
func (*Config) UpdateSingboxInbound ¶
UpdateSingboxInbound updates an existing inbound by tag
func (*Config) UpdateSingboxOutboundDomainStrategies ¶
func (c *Config) UpdateSingboxOutboundDomainStrategies(updates []SingboxOutboundDomainStrategyUpdate) error
func (*Config) UpdateUser ¶
func (*Config) UpdateUserInInbound ¶
func (*Config) UpdateUserRouteTagMembership ¶
func (c *Config) UpdateUserRouteTagMembership(userName string, targetTagIDs []int64, tags []UserRouteTag) ([]UserRouteTag, error)
func (*Config) UpsertSingboxRouteRules ¶
UpsertSingboxRouteRules merges newRules into route.rules, skipping duplicates. Two rules are considered identical when their inbound+protocol+action+outbound fields match.
func (*Config) ValidateConfig ¶
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 Hysteria2User ¶
type InboundBase ¶
type InboundMeta ¶
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 ¶
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) 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 ¶
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 ¶
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 ¶
ListSegments returns segments ordered by start_ts DESC (newest first). limit <= 0 returns all segments.
func (*LogStore) OldestHotTs ¶
OldestHotTs returns the smallest ts currently in singbox_logs (0 if empty).
func (*LogStore) PollAfterID ¶
PollAfterID returns up to limit rows with id > afterID, ordered id ASC. Used for live-tail incremental polling.
func (*LogStore) SegmentStats ¶
SegmentStats returns the count and total size_bytes of all rows in log_segments.
func (*LogStore) SegmentsInRange ¶
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) TailHot ¶
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 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 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 RouteTagRuleResolution ¶
type SamplerRun ¶
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 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 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 SingboxOutboundView ¶
type SingboxRestartRequiredError ¶
func (*SingboxRestartRequiredError) Error ¶
func (e *SingboxRestartRequiredError) Error() string
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 ¶
func (*Store) BulkInsert ¶
func (*Store) CompressOldSamples ¶
func (*Store) CompressOldWGSamples ¶
func (*Store) CountSamples ¶
func (*Store) CreateAdmin ¶
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) DeleteInboundMeta ¶
func (*Store) DeletePanelUser ¶
func (*Store) DeleteSubscriptionRequest ¶
func (*Store) DeleteSubscriptionRequestsByIDs ¶
func (*Store) DeleteSubscriptionRequestsBySubID ¶
func (*Store) DeleteUserMetadata ¶
func (*Store) DeleteUserRouteTag ¶
func (*Store) EnforceSubscriptionQuotas ¶
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 ¶
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 ¶
EnforceUserQuotas evaluates all users with individual quota metadata and bidirectionally enforces them against the live sing-box config.
func (*Store) EnsureDefaultAdmin ¶
func (*Store) EnsureDefaultPanelUser ¶
EnsureDefaultPanelUser migrates existing admins to panel_users and/or bootstraps the initial superuser.
func (*Store) GetActiveUserCount ¶
func (*Store) GetActiveUserCountWithThreshold ¶
func (*Store) GetActiveUsers ¶
func (*Store) GetActiveUsersWithThreshold ¶
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 ¶
GetCombinedReport queries both daily_usage and samples to build a comprehensive report.
func (*Store) GetDashboardPreferences ¶
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) GetLastSeenUserWithTraffic ¶
func (*Store) GetLastSeenWithThreshold ¶
func (*Store) GetMaxTimestamp ¶
func (*Store) GetMaxTimestampForUser ¶
func (*Store) GetPanelUserSubscriptionDefaults ¶
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 (*Store) GetSamplerRuns ¶
func (s *Store) GetSamplerRuns(limit, offset int) ([]SamplerRun, error)
func (*Store) GetSamples ¶
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) 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 ¶
GetWGTrafficDelta returns rx/tx delta between first and last sample in the range.
func (*Store) GetWGTrafficSeries ¶
func (*Store) HasSamples ¶
func (*Store) InsertWGSamples ¶
func (*Store) ListUserRouteTags ¶
func (s *Store) ListUserRouteTags() ([]UserRouteTag, error)
func (*Store) LogSamplerRun ¶
func (*Store) PruneOlderThan ¶
func (*Store) PruneSubscriptionRequestsOlderThan ¶
func (*Store) PruneWGSamplesOlderThan ¶
func (*Store) ReconcileUserQuotaNow ¶
func (*Store) RemoveUserFromSubscriptions ¶
func (*Store) RenameInboundMeta ¶
func (*Store) RenameInboundReferences ¶
func (*Store) RenameUserTrafficIdentity ¶
func (*Store) RunWGSampleTx ¶
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 (*Store) UpdateAdminPassword ¶
func (*Store) UpdateAdminUsername ¶
func (*Store) UpdateDashboardPreferences ¶
func (*Store) UpdatePanelUserPassword ¶
func (*Store) UpdatePanelUserPermissions ¶
func (s *Store) UpdatePanelUserPermissions(username string, perms PanelUserPermissions) error
func (*Store) UpdatePanelUserSubscriptionDefaults ¶
func (*Store) UpdatePanelUsername ¶
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 (*Store) UpsertWGPeer ¶
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 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 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 TrafficStats ¶
type TrafficTotal ¶
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 UserAccount ¶
type UserCounter ¶
type UserInboundInfo ¶
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 V2RayAPI ¶
type V2RayAPI struct {
Listen string `json:"listen,omitempty"`
Stats *V2RayStats `json:"stats,omitempty"`
}
type V2RayStats ¶
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 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 ¶
type WGDailyUsage ¶
WGDailyUsage represents aggregated traffic data for a WG peer on a specific bucket (8h).
type WGPeerMeta ¶
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 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)